Merge branch 'tb/trace2-va-list-fix'
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 10:28:10 +0000 (19:28 +0900)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Apr 2019 10:28:10 +0000 (19:28 +0900)
Fix some code that passed a NULL when a va_list was expected.

* tb/trace2-va-list-fix:
trace2: NULL is not allowed for va_list

153 files changed:
.github/CONTRIBUTING.md
.github/PULL_REQUEST_TEMPLATE.md
.gitignore
.travis.yml
Documentation/.gitignore
Documentation/Makefile
Documentation/RelNotes/2.22.0.txt [new file with mode: 0644]
Documentation/asciidoctor-extensions.rb
Documentation/config/branch.txt
Documentation/config/diff.txt
Documentation/config/fsck.txt
Documentation/config/gc.txt
Documentation/config/gpg.txt
Documentation/config/pull.txt
Documentation/config/rebase.txt
Documentation/diff-options.txt
Documentation/doc-diff
Documentation/git-add.txt
Documentation/git-am.txt
Documentation/git-cherry-pick.txt
Documentation/git-clean.txt
Documentation/git-commit-tree.txt
Documentation/git-config.txt
Documentation/git-fsck.txt
Documentation/git-gc.txt
Documentation/git-grep.txt
Documentation/git-http-backend.txt
Documentation/git-ls-remote.txt
Documentation/git-merge.txt
Documentation/git-notes.txt
Documentation/git-rebase.txt
Documentation/git-reset.txt
Documentation/git-revert.txt
Documentation/git-submodule.txt
Documentation/git-svn.txt
Documentation/git-worktree.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/githooks.txt
Documentation/gitignore.txt
Documentation/gitremote-helpers.txt
Documentation/gitweb.conf.txt
Documentation/glossary-content.txt
Documentation/merge-options.txt
Documentation/rev-list-options.txt
Documentation/technical/directory-rename-detection.txt
Documentation/technical/pack-protocol.txt
GIT-VERSION-GEN
Makefile
RelNotes
apply.c
attr.c
bisect.c
builtin/am.c
builtin/commit-tree.c
builtin/commit.c
builtin/diff.c
builtin/fetch.c
builtin/fsck.c
builtin/help.c
builtin/init-db.c
builtin/log.c
builtin/prune.c
builtin/pull.c
builtin/rebase.c
builtin/receive-pack.c
builtin/replace.c
builtin/rev-list.c
builtin/worktree.c
cache.h
check-racy.c [deleted file]
ci/run-windows-build.sh [deleted file]
compat/bswap.h
config.mak.dev
config.mak.uname
contrib/completion/git-completion.bash
contrib/subtree/git-subtree.sh
convert.c
date.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
fetch-pack.c
git-legacy-rebase.sh [deleted file]
git-send-email.perl
git-submodule.sh
git.c
gitk-git/po/bg.po
help.c
line-log.c
list-objects-filter-options.c
merge-recursive.c
pack-objects.c
pack-objects.h
parse-options.h
path.c
pkt-line.c
pkt-line.h
pretty.c
protocol.c
reachable.c
ref-filter.c
refs/files-backend.c
remote-curl.c
repository.c
revision.c
sequencer.c
setup.c
sha1-name.c
sha1collisiondetection
sha1dc/sha1.c
submodule-config.c
submodule.c
t/README
t/perf/p5304-prune.sh [new file with mode: 0755]
t/perf/perf-lib.sh
t/t0001-init.sh
t/t1060-object-corruption.sh
t/t1415-worktree-refs.sh
t/t1450-fsck.sh
t/t2023-checkout-m.sh
t/t3400-rebase.sh
t/t3404-rebase-interactive.sh
t/t3429-rebase-edit-todo.sh
t/t3600-rm.sh
t/t4014-format-patch.sh
t/t4038-diff-combined.sh
t/t4053-diff-no-index.sh
t/t4150-am.sh
t/t4211-line-log.sh
t/t5304-prune.sh
t/t5400-send-pack.sh
t/t5500-fetch-pack.sh
t/t5503-tagfollow.sh
t/t5512-ls-remote.sh
t/t5515-fetch-merge-logic.sh
t/t5516-fetch-push.sh
t/t5539-fetch-http-shallow.sh
t/t5541-http-push-smart.sh
t/t5551-http-fetch-smart.sh
t/t5552-skipping-fetch-negotiator.sh
t/t5601-clone.sh
t/t5700-protocol-v1.sh
t/t5702-protocol-v2.sh
t/t6030-bisect-porcelain.sh
t/t7406-submodule-update.sh
t/t9902-completion.sh
t/test-lib-functions.sh
t/test-lib.sh
unpack-trees.c
worktree.c
xdiff-interface.c
index 64e605a02b71c51e9f59c429b28961c3152039b9..e7b4e2f3c204c2c94c60222abbc702bd7d72de39 100644 (file)
@@ -5,7 +5,7 @@ Git community does not use github.com for their contributions. Instead, we use
 a mailing list (git@vger.kernel.org) for code submissions, code
 reviews, and bug reports.
 
-Nevertheless, you can use [submitGit](http://submitgit.herokuapp.com/) to
+Nevertheless, you can use [GitGitGadget](https://gitgitgadget.github.io/) to
 conveniently send your Pull Requests commits to our mailing list.
 
 Please read ["A note from the maintainer"](https://git.kernel.org/pub/scm/git/git.git/plain/MaintNotes?h=todo)
index adba13e5baf4603de72341068532e2c7d7d05f75..952c7c3a2aa11ea1087390be61eab6f7c0013599 100644 (file)
@@ -1,7 +1,7 @@
 Thanks for taking the time to contribute to Git! Please be advised that the
 Git community does not use github.com for their contributions. Instead, we use
 a mailing list (git@vger.kernel.org) for code submissions, code reviews, and
-bug reports. Nevertheless, you can use submitGit to conveniently send your Pull
-Requests commits to our mailing list.
+bug reports. Nevertheless, you can use GitGitGadget (https://gitgitgadget.github.io/)
+to conveniently send your Pull Requests commits to our mailing list.
 
 Please read the "guidelines for contributing" linked above!
index 7374587f9df901cba0a6990ad48fac17f8a5be57..5cb84f1d1a9ec556eb2f418da1d174e149a49165 100644 (file)
@@ -82,7 +82,6 @@
 /git-init-db
 /git-interpret-trailers
 /git-instaweb
-/git-legacy-rebase
 /git-log
 /git-ls-files
 /git-ls-remote
index 36cbdea7f4f37e7eb4d5172daa4431cffcb4b46c..ffb1bc46f2d9605f7c3fba478f918fcc288bbdd6 100644 (file)
@@ -21,16 +21,6 @@ matrix:
       compiler:
       addons:
       before_install:
-    - env: jobname=Windows
-      os: linux
-      compiler:
-      addons:
-      before_install:
-      script:
-        - >
-          test "$TRAVIS_REPO_SLUG" != "git/git" ||
-          ci/run-windows-build.sh $TRAVIS_BRANCH $(git rev-parse HEAD)
-      after_failure:
     - env: jobname=Linux32
       os: linux
       compiler:
index 3ef54e0adbad5fbfd4468581037a2dcb9a9a4681..bf2bf271b5678895e94810dcbdca12b0dfb7de91 100644 (file)
@@ -13,3 +13,4 @@ mergetools-*.txt
 manpage-base-url.xsl
 SubmittingPatches.txt
 tmp-doc-diff/
+GIT-ASCIIDOCFLAGS
index 26a2342beaf0132241980dbbcaf8592fd4d183dc..4e4dd7ecf14919fa3d5735daa6b87c8addcff1e8 100644 (file)
@@ -331,6 +331,15 @@ mergetools-list.made: ../git-mergetool--lib.sh $(wildcard ../mergetools/*)
                show_tool_names can_merge "* " || :' >mergetools-merge.txt && \
        date >$@
 
+TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK))
+
+GIT-ASCIIDOCFLAGS: FORCE
+       @FLAGS='$(TRACK_ASCIIDOCFLAGS)'; \
+           if test x"$$FLAGS" != x"`cat GIT-ASCIIDOCFLAGS 2>/dev/null`" ; then \
+               echo >&2 "    * new asciidoc flags"; \
+               echo "$$FLAGS" >GIT-ASCIIDOCFLAGS; \
+            fi
+
 clean:
        $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7
        $(RM) *.texi *.texi+ *.texi++ git.info gitman.info
@@ -340,13 +349,14 @@ clean:
        $(RM) SubmittingPatches.txt
        $(RM) $(cmds_txt) $(mergetools_txt) *.made
        $(RM) manpage-base-url.xsl
+       $(RM) GIT-ASCIIDOCFLAGS
 
-$(MAN_HTML): %.html : %.txt asciidoc.conf
+$(MAN_HTML): %.html : %.txt asciidoc.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_HTML) -d manpage -o $@+ $< && \
        mv $@+ $@
 
-$(OBSOLETE_HTML): %.html : %.txto asciidoc.conf
+$(OBSOLETE_HTML): %.html : %.txto asciidoc.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_HTML) -o $@+ $< && \
        mv $@+ $@
@@ -354,16 +364,16 @@ $(OBSOLETE_HTML): %.html : %.txto asciidoc.conf
 manpage-base-url.xsl: manpage-base-url.xsl.in
        $(QUIET_GEN)sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@
 
-%.1 %.5 %.7 : %.xml manpage-base-url.xsl
+%.1 %.5 %.7 : %.xml manpage-base-url.xsl $(wildcard manpage*.xsl)
        $(QUIET_XMLTO)$(RM) $@ && \
        $(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
 
-%.xml : %.txt asciidoc.conf
+%.xml : %.txt asciidoc.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_XML) -d manpage -o $@+ $< && \
        mv $@+ $@
 
-user-manual.xml: user-manual.txt user-manual.conf
+user-manual.xml: user-manual.txt user-manual.conf asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        $(TXT_TO_XML) -d book -o $@+ $< && \
        mv $@+ $@
@@ -373,7 +383,8 @@ technical/api-index.txt: technical/api-index-skel.txt \
        $(QUIET_GEN)cd technical && '$(SHELL_PATH_SQ)' ./api-index.sh
 
 technical/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
-$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt asciidoc.conf
+$(patsubst %,%.html,$(API_DOCS) technical/api-index $(TECH_DOCS)): %.html : %.txt \
+       asciidoc.conf GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(TXT_TO_HTML) $*.txt
 
 SubmittingPatches.txt: SubmittingPatches
@@ -430,7 +441,7 @@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
 WEBDOC_DEST = /pub/software/scm/git/docs
 
 howto/%.html: ASCIIDOC_EXTRA += -a git-relative-html-prefix=../
-$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
+$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt GIT-ASCIIDOCFLAGS
        $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
        sed -e '1,/^$$/d' $< | \
        $(TXT_TO_HTML) - >$@+ && \
diff --git a/Documentation/RelNotes/2.22.0.txt b/Documentation/RelNotes/2.22.0.txt
new file mode 100644 (file)
index 0000000..5673c06
--- /dev/null
@@ -0,0 +1,189 @@
+Git 2.22 Release Notes
+======================
+
+Updates since v2.21
+-------------------
+
+UI, Workflows & Features
+
+ * "git checkout --no-overlay" can be used to trigger a new mode of
+   checking out paths out of the tree-ish, that allows paths that
+   match the pathspec that are in the current index and working tree
+   and are not in the tree-ish.
+
+ * The %(trailers) formatter in "git log --format=..."  now allows to
+   optionally pick trailers selectively by keyword, show only values,
+   etc.
+
+ * Four new configuration variables {author,committer}.{name,email}
+   have been introduced to override user.{name,email} in more specific
+   cases.
+
+ * Command-line completion (in contrib/) learned to tab-complete the
+   "git submodule absorbgitdirs" subcommand.
+
+ * "git branch" learned a new subcommand "--show-current".
+
+ * Output from "diff --cc" did not show the original paths when the
+   merge involved renames.  A new option adds the paths in the
+   original trees to the output.
+
+ * The command line completion (in contrib/) has been taught to
+   complete more subcommand parameters.
+
+ * The final report from "git bisect" used to show the suspected
+   culprit using a raw "diff-tree", with which there is no output for
+   a merge commit.  This has been updated to use a more modern and
+   human readable output that still is concise enough.
+
+ * "git rebase --rebase-merges" replaces its old "--preserve-merges"
+   option; the latter is now marked as deprecated.
+
+ * Error message given while cloning with --recurse-submodules has
+   been updated.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * The diff machinery, one of the oldest parts of the system, which
+   long predates the parse-options API, uses fairly long and complex
+   handcrafted option parser.  This is being rewritten to use the
+   parse-options API.
+
+ * The implementation of pack-redundant has been updated for
+   performance in a repository with many packfiles.
+
+ * A more structured way to obtain execution trace has been added.
+
+ * "git prune" has been taught to take advantage of reachability
+   bitmap when able.
+
+ * The command line parser of "git commit-tree" has been rewritten to
+   use the parse-options API.
+
+ * Suggest GitGitGadget instead of submitGit as a way to submit
+   patches based on GitHub PR to us.
+
+
+Fixes since v2.21
+-----------------
+
+ * "git prune-packed" did not notice and complain against excess
+   arguments given from the command line, which now it does.
+   (merge 9b0bd87ed2 rj/prune-packed-excess-args later to maint).
+
+ * Split-index fix.
+   (merge 6e37c8ed3c nd/split-index-null-base-fix later to maint).
+
+ * "git diff --no-index" may still want to access Git goodies like
+   --ext-diff and --textconv, but so far these have been ignored,
+   which has been corrected.
+   (merge 287ab28bfa jk/diff-no-index-initialize later to maint).
+
+ * Unify RPC code for smart http in protocol v0/v1 and v2, which fixes
+   a bug in the latter (lack of authentication retry) and generally
+   improves the code base.
+   (merge a97d00799a jt/http-auth-proto-v2-fix later to maint).
+
+ * The include file compat/bswap.h has been updated so that it is safe
+   to (accidentally) include it more than once.
+   (merge 33aa579a55 jk/guard-bswap-header later to maint).
+
+ * The set of header files used by "make hdr-check" unconditionally
+   included sha256/gcrypt.h, even when it is not used, causing the
+   make target to fail.  We now skip it when GCRYPT_SHA256 is not in
+   use.
+   (merge f23aa18e7f rj/hdr-check-gcrypt-fix later to maint).
+
+ * The Makefile uses 'find' utility to enumerate all the *.h header
+   files, which is expensive on platforms with slow filesystems; it
+   now optionally uses "ls-files" if working within a repository,
+   which is a trick similar to how all sources are enumerated to run
+   ETAGS on.
+   (merge 92b88eba9f js/find-lib-h-with-ls-files-when-possible later to maint).
+
+ * "git rebase" that was reimplemented in C did not set ORIG_HEAD
+   correctly, which has been corrected.
+   (merge cbd29ead92 js/rebase-orig-head-fix later to maint).
+
+ * Dev support.
+   (merge f545737144 js/stress-test-ui-tweak later to maint).
+
+ * CFLAGS now can be tweaked when invoking Make while using
+   DEVELOPER=YesPlease; this did not work well before.
+   (merge 6d5d4b4e93 ab/makefile-help-devs-more later to maint).
+
+ * "git fsck --connectivity-only" omits computation necessary to sift
+   the objects that are not reachable from any of the refs into
+   unreachable and dangling.  This is now enabled when dangling
+   objects are requested (which is done by default, but can be
+   overridden with the "--no-dangling" option).
+   (merge 8d8c2a5aef jk/fsck-doc later to maint).
+
+ * On platforms where "git fetch" is killed with SIGPIPE (e.g. OSX),
+   the upload-pack that runs on the other end that hangs up after
+   detecting an error could cause "git fetch" to die with a signal,
+   which led to a flakey test.  "git fetch" now ignores SIGPIPE during
+   the network portion of its operation (this is not a problem as we
+   check the return status from our write(2)s).
+   (merge 143588949c jk/no-sigpipe-during-network-transport later to maint).
+
+ * A recent update broke "is this object available to us?" check for
+   well-known objects like an empty tree (which should yield "yes",
+   even when there is no on-disk object for an empty tree), which has
+   been corrected.
+   (merge f06ab027ef jk/virtual-objects-do-exist later to maint).
+
+ * The setup code has been cleaned up to avoid leaks around the
+   repository_format structure.
+   (merge e8805af1c3 ma/clear-repository-format later to maint).
+
+ * "git config --type=color ..." is meant to replace "git config --get-color"
+   but there is a slight difference that wasn't documented, which is
+   now fixed.
+   (merge cd8e7593b9 jk/config-type-color-ends-with-lf later to maint).
+
+ * When the "clean" filter can reduce the size of a huge file in the
+   working tree down to a small "token" (a la Git LFS), there is no
+   point in allocating a huge scratch area upfront, but the buffer is
+   sized based on the original file size.  The convert mechanism now
+   allocates very minimum and reallocates as it receives the output
+   from the clean filter process.
+   (merge 02156ab031 jh/resize-convert-scratch-buffer later to maint).
+
+ * "git rebase" uses the refs/rewritten/ hierarchy to store its
+   intermediate states, which inherently makes the hierarchy per
+   worktree, but it didn't quite work well.
+   (merge b9317d55a3 nd/rewritten-ref-is-per-worktree later to maint).
+
+ * "git log -L<from>,<to>:<path>" with "-s" did not suppress the patch
+   output as it should.  This has been corrected.
+   (merge 05314efaea jk/line-log-with-patch later to maint).
+
+ * "git worktree add" used to do a "find an available name with stat
+   and then mkdir", which is race-prone.  This has been fixed by using
+   mkdir and reacting to EEXIST in a loop.
+   (merge 7af01f2367 ms/worktree-add-atomic-mkdir later to maint).
+
+ * Build update for SHA-1 with collision detection.
+   (merge 07a20f569b jk/sha1dc later to maint).
+
+ * Code cleanup, docfix, build fix, etc.
+   (merge 11f470aee7 jc/test-yes-doc later to maint).
+   (merge 90503a240b js/doc-symref-in-proto-v1 later to maint).
+   (merge 5c326d1252 jk/unused-params later to maint).
+   (merge 68cabbfda3 dl/doc-submodule-wo-subcommand later to maint).
+   (merge 9903623761 ab/receive-pack-use-after-free-fix later to maint).
+   (merge 1ede45e44b en/merge-options-doc later to maint).
+   (merge 3e14dd2c8e rd/doc-hook-used-in-sample later to maint).
+   (merge c271dc28fd nd/no-more-check-racy later to maint).
+   (merge e6e15194a8 yb/utf-16le-bom-spellfix later to maint).
+   (merge bb101aaf0c rd/attr.c-comment-typofix later to maint).
+   (merge 716a5af812 rd/gc-prune-doc-fix later to maint).
+   (merge 50b206371d js/untravis-windows later to maint).
+   (merge dbf47215e3 js/rebase-recreate-merge later to maint).
+   (merge 56cb2d30f8 dl/reset-doc-no-wrt-abbrev later to maint).
+   (merge 64eca306a2 ja/dir-rename-doc-markup-fix later to maint).
+   (merge af91b0230c dl/ignore-docs later to maint).
+   (merge 59a06e947b ra/t3600-test-path-funcs later to maint).
+   (merge e041d0781b ar/t4150-remove-cruft later to maint).
index ec83b4959eb4d8b278ca6e769cbbaca0cba7cb06..0089e0cfb80df9a283b220ba4187e38f5612557d 100644 (file)
@@ -11,12 +11,12 @@ module Git
       def process(parent, target, attrs)
         if parent.document.basebackend? 'html'
           prefix = parent.document.attr('git-relative-html-prefix')
-          %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>\n)
+          %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>)
         elsif parent.document.basebackend? 'docbook'
           "<citerefentry>\n" \
             "<refentrytitle>#{target}</refentrytitle>" \
             "<manvolnum>#{attrs[1]}</manvolnum>\n" \
-          "</citerefentry>\n"
+          "</citerefentry>"
         end
       end
     end
index 019d60ede2873ffb76e96e75ab0502c8840f75b6..8f4b3faadd47b6c655f403528615ae4f0e0df9f6 100644 (file)
@@ -85,9 +85,9 @@ When `merges`, pass the `--rebase-merges` option to 'git rebase'
 so that the local merge commits are included in the rebase (see
 linkgit:git-rebase[1] for details).
 +
-When preserve, also pass `--preserve-merges` along to 'git rebase'
-so that locally committed merge commits will not be flattened
-by running 'git pull'.
+When `preserve` (deprecated in favor of `merges`), also pass
+`--preserve-merges` along to 'git rebase' so that locally committed merge
+commits will not be flattened by running 'git pull'.
 +
 When the value is `interactive`, the rebase is run in interactive mode.
 +
index e48bb987d789e033e1da012a7f950177848b5b23..2c4c9ba27aa48a2eea4951c8a4cffc4f718a75ce 100644 (file)
@@ -10,7 +10,7 @@ diff.autoRefreshIndex::
 
 diff.dirstat::
        A comma separated list of `--dirstat` parameters specifying the
-       default behavior of the `--dirstat` option to linkgit:git-diff[1]`
+       default behavior of the `--dirstat` option to linkgit:git-diff[1]
        and friends. The defaults can be overridden on the command line
        (using `--dirstat=<param1,param2,...>`). The fallback defaults
        (when not changed by `diff.dirstat`) are `changes,noncumulative,3`.
@@ -73,7 +73,7 @@ diff.external::
        environment variable.  The command is called with parameters
        as described under "git Diffs" in linkgit:git[1].  Note: if
        you want to use an external diff program only on a subset of
-       your files, you might want to use linkgit:gitattributes[5] instead.
+       your files, you might want to use linkgit:gitattributes[5] instead.
 
 diff.ignoreSubmodules::
        Sets the default value of --ignore-submodules. Note that this
index 879c5a29c47ddfee5ef3d0ad96895a787d23d285..450e8c38e34338170a806f9e43a99ac37b2e8f2f 100644 (file)
@@ -23,9 +23,9 @@ When `fsck.<msg-id>` is set, errors can be switched to warnings and
 vice versa by configuring the `fsck.<msg-id>` setting where the
 `<msg-id>` is the fsck message ID and the value is one of `error`,
 `warn` or `ignore`. For convenience, fsck prefixes the error/warning
-with the message ID, e.g. "missingEmail: invalid author/committer line
-- missing email" means that setting `fsck.missingEmail = ignore` will
-hide that issue.
+with the message ID, e.g. "missingEmail: invalid author/committer
+line - missing email" means that setting `fsck.missingEmail = ignore`
+will hide that issue.
 +
 In general, it is better to enumerate existing objects with problems
 with `fsck.skipList`, instead of listing the kind of breakages these
index c6fbb8a96f9ee59dfe93a61e4f7a9e3f95f2d7d9..73c08b0c00cb124b3de230f770a1c48cc27e4a21 100644 (file)
@@ -19,7 +19,7 @@ gc.autoPackLimit::
        When there are more than this many packs that are not
        marked with `*.keep` file in the repository, `git gc
        --auto` consolidates them into one larger pack.  The
-       default value is 50.  Setting this to 0 disables it.
+       default value is 50.  Setting this to 0 disables it.
 
 gc.autoDetach::
        Make `git gc --auto` return immediately and run in background
index 590fe0d4baa1740bc1f2abc38ce73340adf59ed6..f999f8ea491d0238abaca2037535c0374f28bc01 100644 (file)
@@ -16,5 +16,5 @@ gpg.format::
 gpg.<format>.program::
        Use this to customize the program used for the signing format you
        chose. (see `gpg.program` and `gpg.format`) `gpg.program` can still
-       be used as a legacy synonym for `gpg.openpgp.program`. The default
+       be used as a legacy synonym for `gpg.openpgp.program`. The default
        value for `gpg.x509.program` is "gpgsm".
index bb23a9947d78dcbf528b27b0ebb11d3e6e01811a..b87cab31b39c4469fc2528c04bd19b6b96912dd7 100644 (file)
@@ -18,9 +18,9 @@ When `merges`, pass the `--rebase-merges` option to 'git rebase'
 so that the local merge commits are included in the rebase (see
 linkgit:git-rebase[1] for details).
 +
-When preserve, also pass `--preserve-merges` along to 'git rebase'
-so that locally committed merge commits will not be flattened
-by running 'git pull'.
+When `preserve` (deprecated in favor of `merges`), also pass
+`--preserve-merges` along to 'git rebase' so that locally committed merge
+commits will not be flattened by running 'git pull'.
 +
 When the value is `interactive`, the rebase is run in interactive mode.
 +
index 331d250e0468df8ec51bdb3348d6a30274da26ed..d98e32d812e76f24f6eca49e32af910b1ddd0967 100644 (file)
@@ -1,16 +1,9 @@
 rebase.useBuiltin::
-       Set to `false` to use the legacy shellscript implementation of
-       linkgit:git-rebase[1]. Is `true` by default, which means use
-       the built-in rewrite of it in C.
-+
-The C rewrite is first included with Git version 2.20. This option
-serves an an escape hatch to re-enable the legacy version in case any
-bugs are found in the rewrite. This option and the shellscript version
-of linkgit:git-rebase[1] will be removed in some future release.
-+
-If you find some reason to set this option to `false` other than
-one-off testing you should report the behavior difference as a bug in
-git.
+       Unused configuration variable. Used in Git versions 2.20 and
+       2.21 as an escape hatch to enable the legacy shellscript
+       implementation of rebase. Now the built-in rewrite of it in C
+       is always used. Setting this will emit a warning, to alert any
+       remaining users that setting this now does nothing.
 
 rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
index f37374165d19cdf626225764e54d8b4d85c05c65..09faee3b44db2e78ba909d30c62ff105255c7832 100644 (file)
@@ -41,6 +41,16 @@ ifndef::git-format-patch[]
        Implies `-p`.
 endif::git-format-patch[]
 
+--output=<file>::
+       Output to a specific file instead of stdout.
+
+--output-indicator-new=<char>::
+--output-indicator-old=<char>::
+--output-indicator-context=<char>::
+       Specify the character used to indicate new, old or context
+       lines in the generated patch. Normally they are '+', '-' and
+       ' ' respectively.
+
 ifndef::git-format-patch[]
 --raw::
 ifndef::git-log[]
@@ -148,6 +158,7 @@ These parameters can also be set individually with `--stat-width=<width>`,
        number of modified files, as well as number of added and deleted
        lines.
 
+-X[<param1,param2,...>]::
 --dirstat[=<param1,param2,...>]::
        Output the distribution of relative amount of changes for each
        sub-directory. The behavior of `--dirstat` can be customized by
@@ -192,6 +203,12 @@ directories with less than 10% of the total amount of changed files,
 and accumulating child directory counts in the parent directories:
 `--dirstat=files,10,cumulative`.
 
+--cumulative::
+       Synonym for --dirstat=cumulative
+
+--dirstat-by-file[=<param1,param2>...]::
+       Synonym for --dirstat=files,param1,param2...
+
 --summary::
        Output a condensed summary of extended header information
        such as creations, renames and mode changes.
@@ -386,6 +403,9 @@ endif::git-format-patch[]
        Turn off rename detection, even when the configuration
        file gives the default to do so.
 
+--[no-]rename-empty::
+       Whether to use empty blobs as rename source.
+
 ifndef::git-format-patch[]
 --check::
        Warn if changes introduce conflict markers or whitespace errors.
@@ -416,7 +436,7 @@ endif::git-format-patch[]
 
 --binary::
        In addition to `--full-index`, output a binary diff that
-       can be applied with `git-apply`.
+       can be applied with `git-apply`. Implies `--patch`.
 
 --abbrev[=<n>]::
        Instead of showing the full 40-byte hexadecimal object
index 32c83dd26f4adf87fd9d6a3ebc6400f6bc108fc7..3355be479812375d8a01d316d26425c3d14be63d 100755 (executable)
@@ -12,9 +12,16 @@ OPTIONS_SPEC="\
 doc-diff [options] <from> <to> [-- <diff-options>]
 doc-diff (-c|--clean)
 --
-j=n    parallel argument to pass to make
-f      force rebuild; do not rely on cached results
-c,clean        cleanup temporary working files
+j=n                    parallel argument to pass to make
+f                      force rebuild; do not rely on cached results
+c,clean                        cleanup temporary working files
+from-asciidoc          use asciidoc with the 'from'-commit
+from-asciidoctor       use asciidoctor with the 'from'-commit
+asciidoc               use asciidoc with both commits
+to-asciidoc            use asciidoc with the 'to'-commit
+to-asciidoctor         use asciidoctor with the 'to'-commit
+asciidoctor            use asciidoctor with both commits
+cut-header-footer      cut away header and footer
 "
 SUBDIRECTORY_OK=1
 . "$(git --exec-path)/git-sh-setup"
@@ -22,6 +29,9 @@ SUBDIRECTORY_OK=1
 parallel=
 force=
 clean=
+from_program=
+to_program=
+cut_header_footer=
 while test $# -gt 0
 do
        case "$1" in
@@ -31,6 +41,22 @@ do
                clean=t ;;
        -f)
                force=t ;;
+       --from-asciidoctor)
+               from_program=-asciidoctor ;;
+       --to-asciidoctor)
+               to_program=-asciidoctor ;;
+       --asciidoctor)
+               from_program=-asciidoctor
+               to_program=-asciidoctor ;;
+       --from-asciidoc)
+               from_program=-asciidoc ;;
+       --to-asciidoc)
+               to_program=-asciidoc ;;
+       --asciidoc)
+               from_program=-asciidoc
+               to_program=-asciidoc ;;
+       --cut-header-footer)
+               cut_header_footer=-cut-header-footer ;;
        --)
                shift; break ;;
        *)
@@ -79,6 +105,22 @@ then
        ln -s "$dots/config.mak" "$tmp/worktree/config.mak"
 fi
 
+construct_makemanflags () {
+       if test "$1" = "-asciidoc"
+       then
+               echo USE_ASCIIDOCTOR=
+       elif test "$1" = "-asciidoctor"
+       then
+               echo USE_ASCIIDOCTOR=YesPlease
+       fi
+}
+
+from_makemanflags=$(construct_makemanflags "$from_program") &&
+to_makemanflags=$(construct_makemanflags "$to_program") &&
+
+from_dir=$from_oid$from_program$cut_header_footer &&
+to_dir=$to_oid$to_program$cut_header_footer &&
+
 # generate_render_makefile <srcdir> <dstdir>
 generate_render_makefile () {
        find "$1" -type f |
@@ -94,7 +136,7 @@ generate_render_makefile () {
        done
 }
 
-# render_tree <committish_oid>
+# render_tree <committish_oid> <directory_name> <makemanflags>
 render_tree () {
        # Skip install-man entirely if we already have an installed directory.
        # We can't rely on make here, since "install-man" unconditionally
@@ -102,28 +144,44 @@ render_tree () {
        # we then can't rely on during the render step). We use "mv" to make
        # sure we don't get confused by a previous run that failed partway
        # through.
-       if ! test -d "$tmp/installed/$1"
+       oid=$1 &&
+       dname=$2 &&
+       makemanflags=$3 &&
+       if ! test -d "$tmp/installed/$dname"
        then
-               git -C "$tmp/worktree" checkout --detach "$1" &&
+               git -C "$tmp/worktree" checkout --detach "$oid" &&
                make -j$parallel -C "$tmp/worktree" \
+                       $makemanflags \
                        GIT_VERSION=omitted \
                        SOURCE_DATE_EPOCH=0 \
-                       DESTDIR="$tmp/installed/$1+" \
+                       DESTDIR="$tmp/installed/$dname+" \
                        install-man &&
-               mv "$tmp/installed/$1+" "$tmp/installed/$1"
+               mv "$tmp/installed/$dname+" "$tmp/installed/$dname"
        fi &&
 
        # As with "installed" above, we skip the render if it's already been
        # done.  So using make here is primarily just about running in
        # parallel.
-       if ! test -d "$tmp/rendered/$1"
+       if ! test -d "$tmp/rendered/$dname"
        then
-               generate_render_makefile "$tmp/installed/$1" "$tmp/rendered/$1+" |
+               generate_render_makefile "$tmp/installed/$dname" \
+                       "$tmp/rendered/$dname+" |
                make -j$parallel -f - &&
-               mv "$tmp/rendered/$1+" "$tmp/rendered/$1"
+               mv "$tmp/rendered/$dname+" "$tmp/rendered/$dname"
+
+               if test "$cut_header_footer" = "-cut-header-footer"
+               then
+                       for f in $(find "$tmp/rendered/$dname" -type f)
+                       do
+                               tail -n +3 "$f" | head -n -2 |
+                               sed -e '1{/^$/d}' -e '${/^$/d}' >"$f+" &&
+                               mv "$f+" "$f" ||
+                               return 1
+                       done
+               fi
        fi
 }
 
-render_tree $from_oid &&
-render_tree $to_oid &&
-git -C $tmp/rendered diff --no-index "$@" $from_oid $to_oid
+render_tree $from_oid $from_dir $from_makemanflags &&
+render_tree $to_oid $to_dir $to_makemanflags &&
+git -C $tmp/rendered diff --no-index "$@" $from_dir $to_dir
index 37bcab94d5e435849c22ddd0473be5cfb1c56140..8b0e4c7fa8c5922801164a7f847a7baecc456402 100644 (file)
@@ -193,15 +193,6 @@ for "git add --no-all <pathspec>...", i.e. ignored removed files.
        for command-line options).
 
 
-CONFIGURATION
--------------
-
-The optional configuration variable `core.excludesFile` indicates a path to a
-file containing patterns of file names to exclude from git-add, similar to
-$GIT_DIR/info/exclude.  Patterns in the exclude file are used in addition to
-those in info/exclude.  See linkgit:gitignore[5].
-
-
 EXAMPLES
 --------
 
index 6f6c34b0f4bc9ba18ec890dff1a6fe10af2fd68f..fc3b993c3338b5f9f8a034aaade14e77bdcd75b5 100644 (file)
@@ -99,6 +99,11 @@ default.   You can use `--no-utf8` to override this.
        am.threeWay configuration variable. For more information,
        see am.threeWay in linkgit:git-config[1].
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 --ignore-space-change::
 --ignore-whitespace::
 --whitespace=<option>::
index b8cfeec67e5fbdcfe1705a3b249f97b284932e79..d64e72462fed7c7c1cd7f0c5543bcd035ce70247 100644 (file)
@@ -148,6 +148,11 @@ effect to your index in a row.
        Pass the merge strategy-specific option through to the
        merge strategy.  See linkgit:git-merge[1] for details.
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 SEQUENCER SUBCOMMANDS
 ---------------------
 include::sequencer.txt[]
index 03056dad0de5ab6121c1f7a506dc4dacf1f83c7c..db876f7dde9237c47d1083d1649f8f8b077b9c82 100644 (file)
@@ -55,14 +55,13 @@ OPTIONS
 
 -e <pattern>::
 --exclude=<pattern>::
-       In addition to those found in .gitignore (per directory) and
-       $GIT_DIR/info/exclude, also consider these patterns to be in the
-       set of the ignore rules in effect.
+       Use the given exclude pattern in addition to the standard ignore rules
+       (see linkgit:gitignore[5]).
 
 -x::
-       Don't use the standard ignore rules read from .gitignore (per
-       directory) and $GIT_DIR/info/exclude, but do still use the ignore
-       rules given with `-e` options.  This allows removing all untracked
+       Don't use the standard ignore rules (see linkgit:gitignore[5]), but
+       still use the ignore rules given with `-e` options from the command
+       line.  This allows removing all untracked
        files, including build products.  This can be used (possibly in
        conjunction with 'git reset') to create a pristine
        working directory to test a clean build.
index 002dae625e5ab7cb834fd548dc0b4c23072a0b1b..4b90b9c12a4a87fe563d367ab8252750021969d7 100644 (file)
@@ -23,6 +23,10 @@ Creates a new commit object based on the provided tree object and
 emits the new commit object id on stdout. The log message is read
 from the standard input, unless `-m` or `-F` options are given.
 
+The `-m` and `-F` options can be given any number of times, in any
+order. The commit log message will be composed in the order in which
+the options are given.
+
 A commit object may have any number of parents. With exactly one
 parent, it is an ordinary commit. Having more than one parent makes
 the commit a merge between several lines of history. Initial (root)
@@ -41,7 +45,7 @@ state was.
 OPTIONS
 -------
 <tree>::
-       An existing tree object
+       An existing tree object.
 
 -p <parent>::
        Each `-p` indicates the id of a parent commit object.
@@ -52,7 +56,8 @@ OPTIONS
 
 -F <file>::
        Read the commit log message from the given file. Use `-` to read
-       from the standard input.
+       from the standard input. This can be given more than once and the
+       content of each file becomes its own paragraph.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
index 1bfe9f56a7b9b983a2d927406dc17ff384e715a2..ff9310f9588a4a13028d1d4182a056262e1079d4 100644 (file)
@@ -126,7 +126,7 @@ See also <<FILES>>.
 
 --local::
        For writing options: write to the repository `.git/config` file.
-       This is the default behavior.
+       This is the default behavior.
 +
 For reading options: read only from the repository `.git/config` rather than
 from all available files.
@@ -240,7 +240,9 @@ Valid `<type>`'s include:
        output.  The optional `default` parameter is used instead, if
        there is no color configured for `name`.
 +
-`--type=color [--default=<default>]` is preferred over `--get-color`.
+`--type=color [--default=<default>]` is preferred over `--get-color`
+(but note that `--get-color` will omit the trailing newline printed by
+`--type=color`).
 
 -e::
 --edit::
index 55950d9eea9edb5157352fa3e6316ef3507e99bf..e0eae642c10f75cff57c0a9d07420e3218235423 100644 (file)
@@ -62,9 +62,17 @@ index file, all SHA-1 references in `refs` namespace, and all reflogs
        with --no-full.
 
 --connectivity-only::
-       Check only the connectivity of tags, commits and tree objects. By
-       avoiding to unpack blobs, this speeds up the operation, at the
-       expense of missing corrupt objects or other problematic issues.
+       Check only the connectivity of reachable objects, making sure
+       that any objects referenced by a reachable tag, commit, or tree
+       is present. This speeds up the operation by avoiding reading
+       blobs entirely (though it does still check that referenced blobs
+       exist). This will detect corruption in commits and trees, but
+       not do any semantic checks (e.g., for format errors). Corruption
+       in blob objects will not be detected at all.
++
+Unreachable tags, commits, and trees will also be accessed to find the
+tips of dangling segments of history. Use `--no-dangling` if you don't
+care about this output and want to speed it up further.
 
 --strict::
        Enable more strict checking, namely to catch a file mode
index a7442499f6d3985fa2ca57fa827d454b11479705..a7c1b0f60edb6ccd38ddb3ea4624fe0d213820b4 100644 (file)
@@ -76,7 +76,7 @@ be performed as well.
 --prune=<date>::
        Prune loose objects older than date (default is 2 weeks ago,
        overridable by the config variable `gc.pruneExpire`).
-       --prune=all prunes loose objects regardless of their age and
+       --prune=now prunes loose objects regardless of their age and
        increases the risk of corruption if another process is writing to
        the repository concurrently; see "NOTES" below. --prune is on by
        default.
index 84fe236a8ee2fd47814c4c7ee854c47279921169..2d27969057fd241922173d286a048e495b74bff0 100644 (file)
@@ -88,7 +88,7 @@ OPTIONS
        mechanism. Only useful with `--untracked`.
 
 --exclude-standard::
-       Do not pay attention to ignored files specified via the `.gitignore`
+       Do not pay attention to ignored files specified via the `.gitignore`
        mechanism.  Only useful when searching files in the current directory
        with `--no-index`.
 
index bb0db195cebd6b8c3824fde4cc3ccdcec4d96543..558966aa837930538010217752c3d94dee29dccc 100644 (file)
@@ -162,7 +162,7 @@ ScriptAliasMatch ^/git/[^/]*(.*) /usr/libexec/git-core/git-http-backend/storage.
 
 Accelerated static Apache 2.x::
        Similar to the above, but Apache can be used to return static
-       files that are stored on disk.  On many systems this may
+       files that are stored on disk.  On many systems this may
        be more efficient as Apache can ask the kernel to copy the
        file contents from the file system directly to the network:
 +
index b9fd3770a6ce19c341c421e07b68985d89d94df5..0b057cbb100c4a3013b3836f40bb065ebee0b8bd 100644 (file)
@@ -31,7 +31,7 @@ OPTIONS
        displayed.
 
 --refs::
-       Do not show peeled tags or pseudorefs like HEAD in the output.
+       Do not show peeled tags or pseudorefs like `HEAD` in the output.
 
 -q::
 --quiet::
index 4cc86469f3dd45564b40b327d1b39f2bb213bb98..6294dbc09d213815fb3a31328de87af52fcf606a 100644 (file)
@@ -83,7 +83,8 @@ invocations. The automated message can include the branch description.
 If `--log` is specified, a shortlog of the commits being merged
 will be appended to the specified message.
 
---[no-]rerere-autoupdate::
+--rerere-autoupdate::
+--no-rerere-autoupdate::
        Allow the rerere mechanism to update the index with the
        result of auto-conflict resolution if possible.
 
index df2b64dbb618e3cf7c538798f5f18ebc41e7eff6..f56a5a91975d592b19d03edafef943519718c588 100644 (file)
@@ -146,7 +146,7 @@ OPTIONS
 
 -C <object>::
 --reuse-message=<object>::
-       Take the given blob object (for example, another note) as the
+       Take the given blob object (for example, another note) as the
        note message. (Use `git notes copy <object>` instead to
        copy notes between objects.)
 
index 5629ba4c5d2b06385911d2c8ba25a496ce78c263..f5e6ae3907bae3af8a86ae5c43775f9b39c48e47 100644 (file)
@@ -300,6 +300,11 @@ See also INCOMPATIBLE OPTIONS below.
 +
 See also INCOMPATIBLE OPTIONS below.
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
        GPG-sign commits. The `keyid` argument is optional and
@@ -410,14 +415,14 @@ See also INCOMPATIBLE OPTIONS below.
 +
 By default, or when `no-rebase-cousins` was specified, commits which do not
 have `<upstream>` as direct ancestor will keep their original branch point,
-i.e. commits that would be excluded by gitlink:git-log[1]'s
+i.e. commits that would be excluded by linkgit:git-log[1]'s
 `--ancestry-path` option will keep their original ancestry by default. If
 the `rebase-cousins` mode is turned on, such commits are instead rebased
 onto `<upstream>` (or `<onto>`, if specified).
 +
-The `--rebase-merges` mode is similar in spirit to `--preserve-merges`, but
-in contrast to that option works well in interactive rebases: commits can be
-reordered, inserted and dropped at will.
+The `--rebase-merges` mode is similar in spirit to the deprecated
+`--preserve-merges`, but in contrast to that option works well in interactive
+rebases: commits can be reordered, inserted and dropped at will.
 +
 It is currently only possible to recreate the merge commits using the
 `recursive` merge strategy; Different merge strategies can be used only via
@@ -427,9 +432,10 @@ See also REBASING MERGES and INCOMPATIBLE OPTIONS below.
 
 -p::
 --preserve-merges::
-       Recreate merge commits instead of flattening the history by replaying
-       commits a merge commit introduces. Merge conflict resolutions or manual
-       amendments to merge commits are not preserved.
+       [DEPRECATED: use `--rebase-merges` instead] Recreate merge commits
+       instead of flattening the history by replaying commits a merge commit
+       introduces. Merge conflict resolutions or manual amendments to merge
+       commits are not preserved.
 +
 This uses the `--interactive` machinery internally, but combining it
 with the `--interactive` option explicitly is generally not a good
@@ -1020,11 +1026,11 @@ merge cmake
 
 BUGS
 ----
-The todo list presented by `--preserve-merges --interactive` does not
-represent the topology of the revision graph.  Editing commits and
-rewording their commit messages should work fine, but attempts to
-reorder commits tend to produce counterintuitive results. Use
-`--rebase-merges` in such scenarios instead.
+The todo list presented by the deprecated `--preserve-merges --interactive`
+does not represent the topology of the revision graph (use `--rebase-merges`
+instead).  Editing commits and rewording their commit messages should work
+fine, but attempts to reorder commits tend to produce counterintuitive results.
+Use `--rebase-merges` in such scenarios instead.
 
 For example, an attempt to rearrange
 ------------
index 132f8e55f67b2e2a40f0058888f4f8260c51f270..26e746c53f25ce833e7dace94b37b178aca48f4e 100644 (file)
@@ -428,8 +428,8 @@ working index HEAD target         working index HEAD
 
 `reset --merge` is meant to be used when resetting out of a conflicted
 merge. Any mergy operation guarantees that the working tree file that is
-involved in the merge does not have local change wrt the index before
-it starts, and that it writes the result out to the working tree. So if
+involved in the merge does not have a local change with respect to the index
+before it starts, and that it writes the result out to the working tree. So if
 we see some difference between the index and the target and also
 between the index and the working tree, then it means that we are not
 resetting out from a state that a mergy operation left after failing
index 837707a8fdb1760f224cc777f6b2b833a6b90a79..6afccb2f1e29fe588c11e979e0d019edc0596b39 100644 (file)
@@ -101,6 +101,11 @@ effect to your index in a row.
        Pass the merge strategy-specific option through to the
        merge strategy.  See linkgit:git-merge[1] for details.
 
+--rerere-autoupdate::
+--no-rerere-autoupdate::
+       Allow the rerere mechanism to update the index with the
+       result of auto-conflict resolution if possible.
+
 SEQUENCER SUBCOMMANDS
 ---------------------
 include::sequencer.txt[]
index ba3c4df550acfeb04a0a6b753a778816f031492c..2794e2978021c08b613b07aebf36090c7943fe09 100644 (file)
@@ -9,6 +9,7 @@ git-submodule - Initialize, update or inspect submodules
 SYNOPSIS
 --------
 [verse]
+'git submodule' [--quiet] [--cached]
 'git submodule' [--quiet] add [<options>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
@@ -28,6 +29,9 @@ For more information about submodules, see linkgit:gitsubmodules[7].
 
 COMMANDS
 --------
+With no arguments, shows the status of existing submodules.  Several
+subcommands are available to perform operations on the submodules.
+
 add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]::
        Add the given repository as a submodule at the given path
        to the changeset to be committed next to the current
index b99029520d9b17e76ab65b4333a79fe20ed22eff..223788fa3ee070b2919a01e1b4eb4cc55043b2af 100644 (file)
@@ -126,7 +126,7 @@ your Perl's Getopt::Long is < v2.37).
        command-line argument.
 +
 This automatically updates the rev_map if needed (see
-'$GIT_DIR/svn/\*\*/.rev_map.*' in the FILES section below for details).
+'$GIT_DIR/svn/\**/.rev_map.*' in the FILES section below for details).
 
 --localtime;;
        Store Git commit times in the local time zone instead of UTC.  This
@@ -239,7 +239,7 @@ Like 'git rebase'; this requires that the working tree be clean
 and have no uncommitted changes.
 +
 This automatically updates the rev_map if needed (see
-'$GIT_DIR/svn/\*\*/.rev_map.*' in the FILES section below for details).
+'$GIT_DIR/svn/\**/.rev_map.*' in the FILES section below for details).
 
 -l;;
 --local;;
@@ -524,7 +524,7 @@ This will set the property 'svn:keywords' to 'FreeBSD=%H' for the file
        way to repair the repo is to use 'reset'.
 +
 Only the rev_map and refs/remotes/git-svn are changed (see
-'$GIT_DIR/svn/\*\*/.rev_map.*' in the FILES section below for details).
+'$GIT_DIR/svn/\**/.rev_map.*' in the FILES section below for details).
 Follow 'reset' with a 'fetch' and then 'git reset' or 'git rebase' to
 move local branches onto the new tree.
 
@@ -760,7 +760,7 @@ svn-remote.<name>.noMetadata::
 +
 This option can only be used for one-shot imports as 'git svn'
 will not be able to fetch again without metadata. Additionally,
-if you lose your '$GIT_DIR/svn/\*\*/.rev_map.*' files, 'git svn' will not
+if you lose your '$GIT_DIR/svn/\**/.rev_map.*' files, 'git svn' will not
 be able to rebuild them.
 +
 The 'git svn log' command will not work on repositories using
@@ -1154,7 +1154,7 @@ fetching, then $GIT_DIR/svn/.metadata must be manually edited to remove
 
 FILES
 -----
-$GIT_DIR/svn/\*\*/.rev_map.*::
+$GIT_DIR/svn/\**/.rev_map.*::
        Mapping between Subversion revision numbers and Git commit
        names.  In a repository where the noMetadata option is not set,
        this can be rebuilt from the git-svn-id: lines that are at the
index cb86318f3e1b34e0eda5b9886fc934456434e7a8..85d92c9761da226010d1fffe20bbbfc404680c66 100644 (file)
@@ -213,7 +213,7 @@ refs of one working tree from another.
 
 In general, all pseudo refs are per working tree and all refs starting
 with "refs/" are shared. Pseudo refs are ones like HEAD which are
-directly under GIT_DIR instead of inside GIT_DIR/refs. There are one
+directly under GIT_DIR instead of inside GIT_DIR/refs. There is one
 exception to this: refs inside refs/bisect and refs/worktree is not
 shared.
 
index 00156d64aad51cd758e554ada68a52a3e55dfc0c..6d1f2fd9ae9e993e46d935f835bdfec4e6f686e1 100644 (file)
@@ -536,7 +536,6 @@ other
        The command-line parameters passed to the configured command are
        determined by the ssh variant.  See `ssh.variant` option in
        linkgit:git-config[1] for details.
-
 +
 `$GIT_SSH_COMMAND` takes precedence over `$GIT_SSH`, and is interpreted
 by the shell, which allows additional arguments to be included.
index 9b41f81c06ef9fd2386b0e424d4d62cb27195ae3..4fb20cd0e963b6cf52c07c6ae7492adbf35f6cbf 100644 (file)
@@ -18,7 +18,7 @@ A `gitattributes` file is a simple text file that gives
 
 Each line in `gitattributes` file is of form:
 
-       pattern attr1 attr2 ...
+       pattern attr1 attr2 ...
 
 That is, a pattern followed by an attributes list,
 separated by whitespaces. Leading and trailing whitespaces are
@@ -314,8 +314,8 @@ stored as UTF-8 internally. A client without `working-tree-encoding`
 support will checkout `foo.ps1` as UTF-8 encoded file. This will
 typically cause trouble for the users of this file.
 +
-If a Git client, that does not support the `working-tree-encoding`
-attribute, adds a new file `bar.ps1`, then `bar.ps1` will be
+If a Git client that does not support the `working-tree-encoding`
+attribute adds a new file `bar.ps1`, then `bar.ps1` will be
 stored "as-is" internally (in this example probably as UTF-16).
 A client with `working-tree-encoding` support will interpret the
 internal contents as UTF-8 and try to convert it to UTF-16 on checkout.
@@ -346,7 +346,7 @@ automatic line ending conversion based on your platform.
 
 Use the following attributes if your '*.ps1' files are UTF-16 little
 endian encoded without BOM and you want Git to use Windows line endings
-in the working directory (use `UTF-16-LE-BOM` instead of `UTF-16LE` if
+in the working directory (use `UTF-16LE-BOM` instead of `UTF-16LE` if
 you want UTF-16 little endian with BOM).
 Please note, it is highly recommended to
 explicitly define the line endings with `eol` if the `working-tree-encoding`
index 959044347e5ee0daf78b3503794e2bf3c51f0efb..5bf653c111d07e0958840e38187320a433b20d07 100644 (file)
@@ -99,6 +99,10 @@ All the `git commit` hooks are invoked with the environment
 variable `GIT_EDITOR=:` if the command will not bring up an editor
 to modify the commit message.
 
+The default 'pre-commit' hook, when enabled--and with the
+`hooks.allownonascii` config option unset or set to false--prevents
+the use of non-ASCII filenames.
+
 prepare-commit-msg
 ~~~~~~~~~~~~~~~~~~
 
index 1c94f08ff4dd9af173c659fb0b536f6a71a1c252..b5bc9dbff05b293caae7c42e865b19bc067c4d82 100644 (file)
@@ -132,6 +132,14 @@ full pathname may have special meaning:
  - Other consecutive asterisks are considered regular asterisks and
    will match according to the previous rules.
 
+CONFIGURATION
+-------------
+
+The optional configuration variable `core.excludesFile` indicates a path to a
+file containing patterns of file names to exclude, similar to
+`$GIT_DIR/info/exclude`.  Patterns in the exclude file are used in addition to
+those in `$GIT_DIR/info/exclude`.
+
 NOTES
 -----
 
index 9d1459aac6d0b12ad1a87ff25a158dca0f2bf470..4f2905dc5dc695edd88516f99f9e1da0f9f7bebd 100644 (file)
@@ -468,7 +468,7 @@ set by Git if the remote helper has the 'option' capability.
 
 'option dry-run' {'true'|'false'}:
        If true, pretend the operation completed successfully,
-       but don't actually change any repository data.  For most
+       but don't actually change any repository data.  For most
        helpers this only applies to the 'push', if supported.
 
 'option servpath <c-style-quoted-path>'::
index 92535dbac53ac49d89ef6d8ce62dd2920c83c445..b284953f64374e680cd571af0694e9ae6e7c89ee 100644 (file)
@@ -536,7 +536,7 @@ $omit_owner::
 
 $per_request_config::
        If this is set to code reference, it will be run once for each request.
-       You can set parts of configuration that change per session this way.
+       You can set parts of configuration that change per session this way.
        For example, one might use the following code in a gitweb configuration
        file
 +
index 023ca95e7c39d88fcac832d73a7454e9fb71e5a1..8d38ae6010866a157dfdb7d52b58605d1cd2f3b6 100644 (file)
@@ -287,6 +287,15 @@ This commit is referred to as a "merge commit", or sometimes just a
        origin/name-of-upstream-branch, which you can see using
        `git branch -r`.
 
+[[def_overlay]]overlay::
+       Only update and add files to the working directory, but don't
+       delete them, similar to how 'cp -R' would update the contents
+       in the destination directory.  This is the default mode in a
+       <<def_checkout,checkout>> when checking out files from the
+       <<def_index,index>> or a <<def_tree-ish,tree-ish>>.  In
+       contrast, no-overlay mode also deletes tracked files not
+       present in the source, similar to 'rsync --delete'.
+
 [[def_pack]]pack::
        A set of objects which have been compressed into one file (to save space
        or to transmit them efficiently).
index 63a3fc09548abe8d34faab98f183e1817b21b878..92a7d936c1a8fbcc6746a0ddd127e131edb8f2c1 100644 (file)
@@ -3,9 +3,14 @@
        Perform the merge and commit the result. This option can
        be used to override --no-commit.
 +
-With --no-commit perform the merge but pretend the merge
-failed and do not autocommit, to give the user a chance to
-inspect and further tweak the merge result before committing.
+With --no-commit perform the merge and stop just before creating
+a merge commit, to give the user a chance to inspect and further
+tweak the merge result before committing.
++
+Note that fast-forward updates do not create a merge commit and
+therefore there is no way to stop those merges with --no-commit.
+Thus, if you want to ensure your branch is not changed or updated
+by the merge command, use --no-ff with --no-commit.
 
 --edit::
 -e::
index ca959a72862048c205d67576fcd6c538f0c91b26..9cf983d24d630a78427798f60c5d6f45b0b64c19 100644 (file)
@@ -743,7 +743,7 @@ explicitly-given commit or tree.
 
 --filter-print-omitted::
        Only useful with `--filter=`; prints a list of the objects omitted
-       by the filter.  Object IDs are prefixed with a ``~'' character.
+       by the filter.  Object IDs are prefixed with a ``~'' character.
 
 --missing=<missing-action>::
        A debug option to help with future "partial clone" development.
index 1c0086e287eadec2f6e1ffa1ca0dad49d7bbbe28..844629c8c441e786734c42e749293f2a718ed288 100644 (file)
@@ -20,8 +20,8 @@ More interesting possibilities exist, though, such as:
   * one side of history renames x -> z, and the other renames some file to
     x/e, causing the need for the merge to do a transitive rename.
 
-  * one side of history renames x -> z, but also renames all files within
-    x.  For example, x/a -> z/alpha, x/b -> z/bravo, etc.
+  * one side of history renames x -> z, but also renames all files within x.
+    For example, x/a -> z/alpha, x/b -> z/bravo, etc.
 
   * both 'x' and 'y' being merged into a single directory 'z', with a
     directory rename being detected for both x->z and y->z.
index 7a2375a55d074514c5ebd851fe55ff27541c207c..c73e72de0e9ccef9f5ad5143ae9d208a3fef1a14 100644 (file)
@@ -657,14 +657,14 @@ can be rejected.
 An example client/server communication might look like this:
 
 ----
-   S: 007c74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n
+   S: 006274730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n
    S: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe refs/heads/debug\n
    S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/master\n
-   S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n
+   S: 003d74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n
    S: 0000
 
-   C: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n
-   C: 003e74730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n
+   C: 00677d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n
+   C: 006874730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n
    C: 0000
    C: [PACKDATA]
 
index 13f835f9cde4fd2e238db6c11bb2cf38a626a1b2..3fc4065da2ecdb7176766f1c5f5b9243cf4ab718 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.21.0
+DEF_VER=v2.21.GIT
 
 LF='
 '
index 148668368bf1708900bf4a62120004747718e8c9..5e5489aa1a7e2176301eb51f1c7cb3f4333b1b83 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -479,7 +479,11 @@ all::
 #
 # Define DEVELOPER to enable more compiler warnings. Compiler version
 # and family are auto detected, but could be overridden by defining
-# COMPILER_FEATURES (see config.mak.dev)
+# COMPILER_FEATURES (see config.mak.dev). You can still set
+# CFLAGS="..." in combination with DEVELOPER enables, whether that's
+# for tweaking something unrelated (e.g. optimization level), or for
+# selectively overriding something DEVELOPER or one of the DEVOPTS
+# (see just below) brings in.
 #
 # When DEVELOPER is set, DEVOPTS can be used to control compiler
 # options.  This variable contains keywords separated by
@@ -506,17 +510,8 @@ GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
 -include GIT-VERSION-FILE
 
-# CFLAGS and LDFLAGS are for the users to override from the command line.
-
-CFLAGS = -g -O2 -Wall
-LDFLAGS =
-ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
-ALL_LDFLAGS = $(LDFLAGS)
-STRIP ?= strip
-
-# Create as necessary, replace existing, make ranlib unneeded.
-ARFLAGS = rcs
-
+# Set our default configuration.
+#
 # Among the variables below, these:
 #   gitexecdir
 #   template_dir
@@ -561,6 +556,7 @@ perllibdir_relative = $(patsubst $(prefix)/%,%,$(perllibdir))
 
 export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
 
+# Set our default programs
 CC = cc
 AR = ar
 RM = rm -f
@@ -573,29 +569,14 @@ TCLTK_PATH = wish
 XGETTEXT = xgettext
 MSGFMT = msgfmt
 CURL_CONFIG = curl-config
-PTHREAD_LIBS = -lpthread
-PTHREAD_CFLAGS =
 GCOV = gcov
+STRIP = strip
 SPATCH = spatch
 
 export TCL_PATH TCLTK_PATH
 
-# user customisation variable for 'sparse' target
-SPARSE_FLAGS ?=
-# internal/platform customisation variable for 'sparse'
-SP_EXTRA_FLAGS =
-
-SPATCH_FLAGS = --all-includes --patch .
-
-
-
-### --- END CONFIGURATION SECTION ---
-
-# Those must not be GNU-specific; they are shared with perl/ which may
-# be built by a different compiler. (Note that this is an artifact now
-# but it still might be nice to keep that distinction.)
-BASIC_CFLAGS = -I.
-BASIC_LDFLAGS =
+# Set our default LIBS variables
+PTHREAD_LIBS = -lpthread
 
 # Guard against environment variables
 BUILTIN_OBJS =
@@ -632,7 +613,6 @@ SCRIPT_SH += git-merge-one-file.sh
 SCRIPT_SH += git-merge-resolve.sh
 SCRIPT_SH += git-mergetool.sh
 SCRIPT_SH += git-quiltimport.sh
-SCRIPT_SH += git-legacy-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
@@ -842,7 +822,8 @@ VCSSVN_LIB = vcs-svn/lib.a
 
 GENERATED_H += command-list.h
 
-LIB_H = $(shell $(FIND) . \
+LIB_H := $(shell git ls-files '*.h' ':!t/' ':!Documentation/' 2>/dev/null || \
+       $(FIND) . \
        -name .git -prune -o \
        -name t -prune -o \
        -name Documentation -prune -o \
@@ -1176,6 +1157,25 @@ ifeq ($(wildcard sha1collisiondetection/lib/sha1.h),sha1collisiondetection/lib/s
 DC_SHA1_SUBMODULE = auto
 endif
 
+# Set CFLAGS, LDFLAGS and other *FLAGS variables. These might be
+# tweaked by config.* below as well as the command-line, both of
+# which'll override these defaults.
+CFLAGS = -g -O2 -Wall
+LDFLAGS =
+BASIC_CFLAGS = -I.
+BASIC_LDFLAGS =
+
+# library flags
+ARFLAGS = rcs
+PTHREAD_CFLAGS =
+
+# For the 'sparse' target
+SPARSE_FLAGS ?=
+SP_EXTRA_FLAGS =
+
+# For the 'coccicheck' target
+SPATCH_FLAGS = --all-includes --patch .
+
 include config.mak.uname
 -include config.mak.autogen
 -include config.mak
@@ -1184,6 +1184,9 @@ ifdef DEVELOPER
 include config.mak.dev
 endif
 
+ALL_CFLAGS = $(DEVELOPER_CFLAGS) $(CPPFLAGS) $(CFLAGS)
+ALL_LDFLAGS = $(LDFLAGS)
+
 comma := ,
 empty :=
 space := $(empty) $(empty)
@@ -1194,6 +1197,7 @@ BASIC_CFLAGS += -fsanitize=$(SANITIZE) -fno-sanitize-recover=$(SANITIZE)
 BASIC_CFLAGS += -fno-omit-frame-pointer
 ifneq ($(filter undefined,$(SANITIZERS)),)
 BASIC_CFLAGS += -DNO_UNALIGNED_LOADS
+BASIC_CFLAGS += -DSHA1DC_FORCE_ALIGNED_ACCESS
 endif
 ifneq ($(filter leak,$(SANITIZERS)),)
 BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
@@ -2376,7 +2380,7 @@ else
 # should _not_ be included here, since they are necessary even when
 # building an object for the first time.
 
-$(OBJECTS): $(LIB_H)
+$(OBJECTS): $(LIB_H) $(GENERATED_H)
 endif
 
 exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
@@ -2749,7 +2753,10 @@ $(SP_OBJ): %.sp: %.c GIT-CFLAGS FORCE
 sparse: $(SP_OBJ)
 
 GEN_HDRS := command-list.h unicode-width.h
-EXCEPT_HDRS := $(GEN_HDRS) compat% xdiff%
+EXCEPT_HDRS := $(GEN_HDRS) compat/% xdiff/%
+ifndef GCRYPT_SHA256
+       EXCEPT_HDRS += sha256/gcrypt.h
+endif
 CHK_HDRS = $(filter-out $(EXCEPT_HDRS),$(patsubst ./%,%,$(LIB_H)))
 HCO = $(patsubst %.h,%.hco,$(CHK_HDRS))
 
index 31e21359a89066faf934359889ac76924dd86893..0b6d9fdbcf0cc440914446e494fde666c893562f 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.21.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.22.0.txt
\ No newline at end of file
diff --git a/apply.c b/apply.c
index 892ede5a318f751c80fcceab036a8cbaee391774..f15afa9f6af98ae41af60eb2296ee35d38ccc7fd 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -56,6 +56,10 @@ static int parse_whitespace_option(struct apply_state *state, const char *option
                state->ws_error_action = correct_ws_error;
                return 0;
        }
+       /*
+        * Please update $__git_whitespacelist in git-completion.bash
+        * when you add new options.
+        */
        return error(_("unrecognized whitespace option '%s'"), option);
 }
 
diff --git a/attr.c b/attr.c
index fdd110bec55cb3bc5c8ebbb8cffbc33cced530b2..93dc16b59cd6eff1d5c962ac2c4b01662948a93e 100644 (file)
--- a/attr.c
+++ b/attr.c
@@ -431,14 +431,14 @@ static struct match_attr *parse_attr_line(const char *line, const char *src,
  * Like info/exclude and .gitignore, the attribute information can
  * come from many places.
  *
- * (1) .gitattribute file of the same directory;
- * (2) .gitattribute file of the parent directory if (1) does not have
+ * (1) .gitattributes file of the same directory;
+ * (2) .gitattributes file of the parent directory if (1) does not have
  *      any match; this goes recursively upwards, just like .gitignore.
  * (3) $GIT_DIR/info/attributes, which overrides both of the above.
  *
  * In the same file, later entries override the earlier match, so in the
  * global list, we would have entries from info/attributes the earliest
- * (reading the file from top to bottom), .gitattribute of the root
+ * (reading the file from top to bottom), .gitattributes of the root
  * directory (again, reading the file from top to bottom) down to the
  * current directory, and then scan the list backwards to find the first match.
  * This is exactly the same as what is_excluded() does in dir.c to deal with
@@ -899,7 +899,7 @@ static void prepare_attr_stack(const struct index_state *istate,
         * set of attribute definitions, followed by the contents
         * of $(prefix)/etc/gitattributes and a file specified by
         * core.attributesfile.  Then, contents from
-        * .gitattribute files from directories closer to the
+        * .gitattributes files from directories closer to the
         * root to the ones in deeper directories are pushed
         * to the stack.  Finally, at the very top of the stack
         * we always keep the contents of $GIT_DIR/info/attributes.
index 3af955c4bc4e1c7cd155a5f2e460cee38af732cd..e87ac29a51be4126415aed1bc9f4638660232010 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -896,24 +896,15 @@ static void show_diff_tree(struct repository *r,
                           const char *prefix,
                           struct commit *commit)
 {
+       const char *argv[] = {
+               "diff-tree", "--pretty", "--stat", "--summary", "--cc", NULL
+       };
        struct rev_info opt;
 
-       /* diff-tree init */
+       git_config(git_diff_ui_config, NULL);
        repo_init_revisions(r, &opt, prefix);
-       git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
-       opt.abbrev = 0;
-       opt.diff = 1;
 
-       /* This is what "--pretty" does */
-       opt.verbose_header = 1;
-       opt.use_terminator = 0;
-       opt.commit_format = CMIT_FMT_DEFAULT;
-
-       /* diff-tree init */
-       if (!opt.diffopt.output_format)
-               opt.diffopt.output_format = DIFF_FORMAT_RAW;
-
-       setup_revisions(0, NULL, &opt, NULL);
+       setup_revisions(ARRAY_SIZE(argv) - 1, argv, &opt, NULL);
        log_tree_commit(&opt, commit);
 }
 
index 86e33495b039bd44d4b59625388d55cd624ccd26..4fb107a9d1bdf36ff4c71d761abdda4d50d0e24b 100644 (file)
@@ -2121,6 +2121,10 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
                *opt_value = PATCH_FORMAT_HG;
        else if (!strcmp(arg, "mboxrd"))
                *opt_value = PATCH_FORMAT_MBOXRD;
+       /*
+        * Please update $__git_patchformat in git-completion.bash
+        * when you add new options
+        */
        else
                return error(_("Invalid value for --patch-format: %s"), arg);
        return 0;
index 12cc403bd7eac3f3c195ce6533feee1865139bae..b866d8395104e61b37ba6eedc1c538d9ba1faabf 100644 (file)
 #include "builtin.h"
 #include "utf8.h"
 #include "gpg-interface.h"
+#include "parse-options.h"
 
-static const char commit_tree_usage[] = "git commit-tree [(-p <sha1>)...] [-S[<keyid>]] [-m <message>] [-F <file>] <sha1>";
+static const char * const commit_tree_usage[] = {
+       N_("git commit-tree [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...] "
+               "[(-F <file>)...] <tree>"),
+       NULL
+};
 
 static const char *sign_commit;
 
@@ -23,7 +28,7 @@ static void new_parent(struct commit *parent, struct commit_list **parents_p)
        struct commit_list *parents;
        for (parents = *parents_p; parents; parents = parents->next) {
                if (parents->item == parent) {
-                       error("duplicate parent %s ignored", oid_to_hex(oid));
+                       error(_("duplicate parent %s ignored"), oid_to_hex(oid));
                        return;
                }
                parents_p = &parents->next;
@@ -39,91 +44,100 @@ static int commit_tree_config(const char *var, const char *value, void *cb)
        return git_default_config(var, value, cb);
 }
 
+static int parse_parent_arg_callback(const struct option *opt,
+               const char *arg, int unset)
+{
+       struct object_id oid;
+       struct commit_list **parents = opt->value;
+
+       BUG_ON_OPT_NEG_NOARG(unset, arg);
+
+       if (get_oid_commit(arg, &oid))
+               die(_("not a valid object name %s"), arg);
+
+       assert_oid_type(&oid, OBJ_COMMIT);
+       new_parent(lookup_commit(the_repository, &oid), parents);
+       return 0;
+}
+
+static int parse_message_arg_callback(const struct option *opt,
+               const char *arg, int unset)
+{
+       struct strbuf *buf = opt->value;
+
+       BUG_ON_OPT_NEG_NOARG(unset, arg);
+
+       if (buf->len)
+               strbuf_addch(buf, '\n');
+       strbuf_addstr(buf, arg);
+       strbuf_complete_line(buf);
+
+       return 0;
+}
+
+static int parse_file_arg_callback(const struct option *opt,
+               const char *arg, int unset)
+{
+       int fd;
+       struct strbuf *buf = opt->value;
+
+       BUG_ON_OPT_NEG_NOARG(unset, arg);
+
+       if (buf->len)
+               strbuf_addch(buf, '\n');
+       if (!strcmp(arg, "-"))
+               fd = 0;
+       else {
+               fd = open(arg, O_RDONLY);
+               if (fd < 0)
+                       die_errno(_("git commit-tree: failed to open '%s'"), arg);
+       }
+       if (strbuf_read(buf, fd, 0) < 0)
+               die_errno(_("git commit-tree: failed to read '%s'"), arg);
+       if (fd && close(fd))
+               die_errno(_("git commit-tree: failed to close '%s'"), arg);
+
+       return 0;
+}
+
 int cmd_commit_tree(int argc, const char **argv, const char *prefix)
 {
-       int i, got_tree = 0;
+       static struct strbuf buffer = STRBUF_INIT;
        struct commit_list *parents = NULL;
        struct object_id tree_oid;
        struct object_id commit_oid;
-       struct strbuf buffer = STRBUF_INIT;
+
+       struct option options[] = {
+               { OPTION_CALLBACK, 'p', NULL, &parents, N_("parent"),
+                       N_("id of a parent commit object"), PARSE_OPT_NONEG,
+                       parse_parent_arg_callback },
+               { OPTION_CALLBACK, 'm', NULL, &buffer, N_("message"),
+                       N_("commit message"), PARSE_OPT_NONEG,
+                       parse_message_arg_callback },
+               { OPTION_CALLBACK, 'F', NULL, &buffer, N_("file"),
+                       N_("read commit log message from file"), PARSE_OPT_NONEG,
+                       parse_file_arg_callback },
+               { OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
+                       N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
+               OPT_END()
+       };
 
        git_config(commit_tree_config, NULL);
 
        if (argc < 2 || !strcmp(argv[1], "-h"))
-               usage(commit_tree_usage);
-
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-               if (!strcmp(arg, "-p")) {
-                       struct object_id oid;
-                       if (argc <= ++i)
-                               usage(commit_tree_usage);
-                       if (get_oid_commit(argv[i], &oid))
-                               die("Not a valid object name %s", argv[i]);
-                       assert_oid_type(&oid, OBJ_COMMIT);
-                       new_parent(lookup_commit(the_repository, &oid),
-                                                &parents);
-                       continue;
-               }
+               usage_with_options(commit_tree_usage, options);
 
-               if (!strcmp(arg, "--gpg-sign")) {
-                   sign_commit = "";
-                   continue;
-               }
+       argc = parse_options(argc, argv, prefix, options, commit_tree_usage, 0);
 
-               if (skip_prefix(arg, "-S", &sign_commit) ||
-                       skip_prefix(arg, "--gpg-sign=", &sign_commit))
-                       continue;
+       if (argc != 1)
+               die(_("must give exactly one tree"));
 
-               if (!strcmp(arg, "--no-gpg-sign")) {
-                       sign_commit = NULL;
-                       continue;
-               }
-
-               if (!strcmp(arg, "-m")) {
-                       if (argc <= ++i)
-                               usage(commit_tree_usage);
-                       if (buffer.len)
-                               strbuf_addch(&buffer, '\n');
-                       strbuf_addstr(&buffer, argv[i]);
-                       strbuf_complete_line(&buffer);
-                       continue;
-               }
-
-               if (!strcmp(arg, "-F")) {
-                       int fd;
-
-                       if (argc <= ++i)
-                               usage(commit_tree_usage);
-                       if (buffer.len)
-                               strbuf_addch(&buffer, '\n');
-                       if (!strcmp(argv[i], "-"))
-                               fd = 0;
-                       else {
-                               fd = open(argv[i], O_RDONLY);
-                               if (fd < 0)
-                                       die_errno("git commit-tree: failed to open '%s'",
-                                                 argv[i]);
-                       }
-                       if (strbuf_read(&buffer, fd, 0) < 0)
-                               die_errno("git commit-tree: failed to read '%s'",
-                                         argv[i]);
-                       if (fd && close(fd))
-                               die_errno("git commit-tree: failed to close '%s'",
-                                         argv[i]);
-                       continue;
-               }
-
-               if (get_oid_tree(arg, &tree_oid))
-                       die("Not a valid object name %s", arg);
-               if (got_tree)
-                       die("Cannot give more than one trees");
-               got_tree = 1;
-       }
+       if (get_oid_tree(argv[0], &tree_oid))
+               die(_("not a valid object name %s"), argv[0]);
 
        if (!buffer.len) {
                if (strbuf_read(&buffer, 0, 0) < 0)
-                       die_errno("git commit-tree: failed to read");
+                       die_errno(_("git commit-tree: failed to read"));
        }
 
        if (commit_tree(buffer.buf, buffer.len, &tree_oid, parents, &commit_oid,
index 8d7a613fda3595380a84d97bbaa7c203954e8dd0..f17537474a9d0ed9672393fc5dc3845932dd4dd4 100644 (file)
@@ -1039,6 +1039,10 @@ static void handle_untracked_files_arg(struct wt_status *s)
                s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
        else if (!strcmp(untracked_files_arg, "all"))
                s->show_untracked_files = SHOW_ALL_UNTRACKED_FILES;
+       /*
+        * Please update $__git_untracked_file_modes in
+        * git-completion.bash when you add new options
+        */
        else
                die(_("Invalid untracked files mode '%s'"), untracked_files_arg);
 }
@@ -1180,6 +1184,10 @@ static int parse_and_validate_options(int argc, const char *argv[],
        else if (!strcmp(cleanup_arg, "scissors"))
                cleanup_mode = use_editor ? COMMIT_MSG_CLEANUP_SCISSORS :
                                            COMMIT_MSG_CLEANUP_SPACE;
+       /*
+        * Please update _git_commit() in git-completion.bash when you
+        * add new options.
+        */
        else
                die(_("Invalid cleanup mode %s"), cleanup_arg);
 
index 9f6109224b7ea75689e9780c5f79343f55e1e3e5..53d4234ff4812845459556b1257e779c528250b8 100644 (file)
@@ -338,21 +338,23 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                       "--no-index" : "[--no-index]");
 
        }
-       if (no_index)
-               /* If this is a no-index diff, just run it and exit there. */
-               diff_no_index(the_repository, &rev, argc, argv);
-
-       /* Otherwise, we are doing the usual "git" diff */
-       rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
 
-       /* Scale to real terminal size and respect statGraphWidth config */
+       /* Set up defaults that will apply to both no-index and regular diffs. */
        rev.diffopt.stat_width = -1;
        rev.diffopt.stat_graph_width = -1;
-
-       /* Default to let external and textconv be used */
        rev.diffopt.flags.allow_external = 1;
        rev.diffopt.flags.allow_textconv = 1;
 
+       /* If this is a no-index diff, just run it and exit there. */
+       if (no_index)
+               diff_no_index(&rev, argc, argv);
+
+       /*
+        * Otherwise, we are doing the usual "git" diff; set up any
+        * further defaults that apply to regular diffs.
+        */
+       rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
+
        /*
         * Default to intent-to-add entries invisible in the
         * index. This makes them show up as new files in diff-files
index b620fd54b4e95cad77532ec3fe02e2ff1179c431..4ba63d5ac642844832a5c832cea93ddf99507764 100644 (file)
@@ -1556,7 +1556,9 @@ static int fetch_one(struct remote *remote, int argc, const char **argv, int pru
 
        sigchain_push_common(unlock_pack_on_signal);
        atexit(unlock_pack);
+       sigchain_push(SIGPIPE, SIG_IGN);
        exit_code = do_fetch(gtransport, &rs);
+       sigchain_pop(SIGPIPE);
        refspec_clear(&rs);
        transport_disconnect(gtransport);
        gtransport = NULL;
index bb4227bebc606dfac8337d7aa3e78705113a79b5..d26fb0a04472b18a856658cf2800dd9655a6bf24 100644 (file)
@@ -235,6 +235,48 @@ static int mark_used(struct object *obj, int type, void *data, struct fsck_optio
        return 0;
 }
 
+static void mark_unreachable_referents(const struct object_id *oid)
+{
+       struct fsck_options options = FSCK_OPTIONS_DEFAULT;
+       struct object *obj = lookup_object(the_repository, oid->hash);
+
+       if (!obj || !(obj->flags & HAS_OBJ))
+               return; /* not part of our original set */
+       if (obj->flags & REACHABLE)
+               return; /* reachable objects already traversed */
+
+       /*
+        * Avoid passing OBJ_NONE to fsck_walk, which will parse the object
+        * (and we want to avoid parsing blobs).
+        */
+       if (obj->type == OBJ_NONE) {
+               enum object_type type = oid_object_info(the_repository,
+                                                       &obj->oid, NULL);
+               if (type > 0)
+                       object_as_type(the_repository, obj, type, 0);
+       }
+
+       options.walk = mark_used;
+       fsck_walk(obj, NULL, &options);
+}
+
+static int mark_loose_unreachable_referents(const struct object_id *oid,
+                                           const char *path,
+                                           void *data)
+{
+       mark_unreachable_referents(oid);
+       return 0;
+}
+
+static int mark_packed_unreachable_referents(const struct object_id *oid,
+                                            struct packed_git *pack,
+                                            uint32_t pos,
+                                            void *data)
+{
+       mark_unreachable_referents(oid);
+       return 0;
+}
+
 /*
  * Check a single reachable object
  */
@@ -347,6 +389,26 @@ static void check_connectivity(void)
        /* Traverse the pending reachable objects */
        traverse_reachable();
 
+       /*
+        * With --connectivity-only, we won't have actually opened and marked
+        * unreachable objects with USED. Do that now to make --dangling, etc
+        * accurate.
+        */
+       if (connectivity_only && (show_dangling || write_lost_and_found)) {
+               /*
+                * Even though we already have a "struct object" for each of
+                * these in memory, we must not iterate over the internal
+                * object hash as we do below. Our loop would potentially
+                * resize the hash, making our iteration invalid.
+                *
+                * Instead, we'll just go back to the source list of objects,
+                * and ignore any that weren't present in our earlier
+                * traversal.
+                */
+               for_each_loose_object(mark_loose_unreachable_referents, NULL, 0);
+               for_each_packed_object(mark_packed_unreachable_referents, NULL, 0);
+       }
+
        /* Look up all the requirements, warn about missing objects.. */
        max = get_max_object_index();
        if (verbose)
index 7739a5c1551426fd2302aaf5daa10e454d174195..e5590d7787c50af121db0ba7e6221e89c6785df1 100644 (file)
@@ -70,6 +70,10 @@ static enum help_format parse_help_format(const char *format)
                return HELP_FORMAT_INFO;
        if (!strcmp(format, "web") || !strcmp(format, "html"))
                return HELP_FORMAT_WEB;
+       /*
+        * Please update _git_config() in git-completion.bash when you
+        * add new help formats.
+        */
        die(_("unrecognized help format '%s'"), format);
 }
 
index 93eff7618cf1b98e3c69a7f1f159063e9e73dbe3..6ca002893f47516ee8963db09d60b3716b60a205 100644 (file)
@@ -96,7 +96,7 @@ static void copy_templates(const char *template_dir)
        struct strbuf path = STRBUF_INIT;
        struct strbuf template_path = STRBUF_INIT;
        size_t template_len;
-       struct repository_format template_format;
+       struct repository_format template_format = REPOSITORY_FORMAT_INIT;
        struct strbuf err = STRBUF_INIT;
        DIR *dir;
        char *to_free = NULL;
@@ -148,6 +148,7 @@ static void copy_templates(const char *template_dir)
        free(to_free);
        strbuf_release(&path);
        strbuf_release(&template_path);
+       clear_repository_format(&template_format);
 }
 
 static int git_init_db_config(const char *k, const char *v, void *cb)
@@ -155,6 +156,9 @@ static int git_init_db_config(const char *k, const char *v, void *cb)
        if (!strcmp(k, "init.templatedir"))
                return git_config_pathname(&init_db_template_dir, k, v);
 
+       if (starts_with(k, "core."))
+               return platform_core_config(k, v, cb);
+
        return 0;
 }
 
@@ -185,6 +189,7 @@ static int create_default_files(const char *template_path,
        struct strbuf err = STRBUF_INIT;
 
        /* Just look for `init.templatedir` */
+       init_db_template_dir = NULL; /* re-set in case it was set before */
        git_config(git_init_db_config, NULL);
 
        /*
@@ -361,6 +366,9 @@ int init_db(const char *git_dir, const char *real_git_dir,
        }
        startup_info->have_repository = 1;
 
+       /* Just look for `core.hidedotfiles` */
+       git_config(git_init_db_config, NULL);
+
        safe_create_dir(git_dir, 0);
 
        init_is_bare_repository = is_bare_repository();
index 57869267d8d75e06a1a34e4dea104102aac21a65..e63c8c2958276d17793ecc0cb15ed8945ee6caf6 100644 (file)
@@ -84,6 +84,10 @@ static int parse_decoration_style(const char *value)
                return DECORATE_SHORT_REFS;
        else if (!strcmp(value, "auto"))
                return auto_decoration_style();
+       /*
+        * Please update _git_log() in git-completion.bash when you
+        * add new decoration styles.
+        */
        return -1;
 }
 
@@ -513,7 +517,7 @@ static int show_blob_object(const struct object_id *oid, struct rev_info *rev, c
        if (get_oid_with_context(the_repository, obj_name,
                                 GET_OID_RECORD_PATH,
                                 &oidc, &obj_context))
-               die(_("Not a valid object name %s"), obj_name);
+               die(_("not a valid object name %s"), obj_name);
        if (!obj_context.path ||
            !textconv_object(the_repository, obj_context.path,
                             obj_context.mode, &oidc, 1, &buf, &size)) {
@@ -537,7 +541,7 @@ static int show_tag_object(const struct object_id *oid, struct rev_info *rev)
        int offset = 0;
 
        if (!buf)
-               return error(_("Could not read object %s"), oid_to_hex(oid));
+               return error(_("could not read object %s"), oid_to_hex(oid));
 
        assert(type == OBJ_TAG);
        while (offset < size && buf[offset] != '\n') {
@@ -631,7 +635,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                                break;
                        o = parse_object(the_repository, &t->tagged->oid);
                        if (!o)
-                               ret = error(_("Could not read object %s"),
+                               ret = error(_("could not read object %s"),
                                            oid_to_hex(&t->tagged->oid));
                        objects[i].item = o;
                        i--;
@@ -656,7 +660,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
                        ret = cmd_log_walk(&rev);
                        break;
                default:
-                       ret = error(_("Unknown type: %d"), o->type);
+                       ret = error(_("unknown type: %d"), o->type);
                }
        }
        free(objects);
@@ -894,7 +898,7 @@ static int open_next_file(struct commit *commit, const char *subject,
                printf("%s\n", filename.buf + outdir_offset);
 
        if ((rev->diffopt.file = fopen(filename.buf, "w")) == NULL) {
-               error_errno(_("Cannot open patch file %s"), filename.buf);
+               error_errno(_("cannot open patch file %s"), filename.buf);
                strbuf_release(&filename);
                return -1;
        }
@@ -911,7 +915,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
        unsigned flags1, flags2;
 
        if (rev->pending.nr != 2)
-               die(_("Need exactly one range."));
+               die(_("need exactly one range"));
 
        o1 = rev->pending.objects[0].item;
        o2 = rev->pending.objects[1].item;
@@ -921,7 +925,7 @@ static void get_patch_ids(struct rev_info *rev, struct patch_ids *ids)
        c2 = lookup_commit_reference(the_repository, &o2->oid);
 
        if ((flags1 & UNINTERESTING) == (flags2 & UNINTERESTING))
-               die(_("Not a range."));
+               die(_("not a range"));
 
        init_patch_ids(the_repository, ids);
 
@@ -1044,13 +1048,13 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
        struct commit *head = list[0];
 
        if (!cmit_fmt_is_mail(rev->commit_format))
-               die(_("Cover letter needs email format"));
+               die(_("cover letter needs email format"));
 
        committer = git_committer_info(0);
 
        if (!use_stdout &&
            open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
-               return;
+               die(_("failed to create cover-letter file"));
 
        log_write_email_headers(rev, head, &pp.after_subject, &need_8bit_cte, 0);
 
@@ -1214,7 +1218,7 @@ static int output_directory_callback(const struct option *opt, const char *arg,
        const char **dir = (const char **)opt->value;
        BUG_ON_OPT_NEG(unset);
        if (*dir)
-               die(_("Two output directories?"));
+               die(_("two output directories?"));
        *dir = arg;
        return 0;
 }
@@ -1228,6 +1232,10 @@ static int thread_callback(const struct option *opt, const char *arg, int unset)
                *thread = THREAD_SHALLOW;
        else if (!strcmp(arg, "deep"))
                *thread = THREAD_DEEP;
+       /*
+        * Please update _git_formatpatch() in git-completion.bash
+        * when you add new options.
+        */
        else
                return 1;
        return 0;
@@ -1321,7 +1329,7 @@ static struct commit *get_base_commit(const char *base_commit,
        if (base_commit && strcmp(base_commit, "auto")) {
                base = lookup_commit_reference_by_name(base_commit);
                if (!base)
-                       die(_("Unknown commit %s"), base_commit);
+                       die(_("unknown commit %s"), base_commit);
        } else if ((base_commit && !strcmp(base_commit, "auto")) || base_auto) {
                struct branch *curr_branch = branch_get(NULL);
                const char *upstream = branch_get_upstream(curr_branch, NULL);
@@ -1331,18 +1339,18 @@ static struct commit *get_base_commit(const char *base_commit,
                        struct object_id oid;
 
                        if (get_oid(upstream, &oid))
-                               die(_("Failed to resolve '%s' as a valid ref."), upstream);
+                               die(_("failed to resolve '%s' as a valid ref"), upstream);
                        commit = lookup_commit_or_die(&oid, "upstream base");
                        base_list = get_merge_bases_many(commit, total, list);
                        /* There should be one and only one merge base. */
                        if (!base_list || base_list->next)
-                               die(_("Could not find exact merge base."));
+                               die(_("could not find exact merge base"));
                        base = base_list->item;
                        free_commit_list(base_list);
                } else {
-                       die(_("Failed to get upstream, if you want to record base commit automatically,\n"
+                       die(_("failed to get upstream, if you want to record base commit automatically,\n"
                              "please use git branch --set-upstream-to to track a remote branch.\n"
-                             "Or you could specify base commit by --base=<base-commit-id> manually."));
+                             "Or you could specify base commit by --base=<base-commit-id> manually"));
                }
        }
 
@@ -1360,7 +1368,7 @@ static struct commit *get_base_commit(const char *base_commit,
                        struct commit_list *merge_base;
                        merge_base = get_merge_bases(rev[2 * i], rev[2 * i + 1]);
                        if (!merge_base || merge_base->next)
-                               die(_("Failed to find exact merge base"));
+                               die(_("failed to find exact merge base"));
 
                        rev[i] = merge_base->item;
                }
@@ -1739,7 +1747,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                if (use_stdout)
                        die(_("standard output, or directory, which one?"));
                if (mkdir(output_directory, 0777) < 0 && errno != EEXIST)
-                       die_errno(_("Could not create directory '%s'"),
+                       die_errno(_("could not create directory '%s'"),
                                  output_directory);
        }
 
@@ -1941,7 +1949,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
 
                if (!use_stdout &&
                    open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
-                       die(_("Failed to create output files"));
+                       die(_("failed to create output files"));
                shown = log_tree_commit(&rev, commit);
                free_commit_buffer(the_repository->parsed_objects,
                                   commit);
@@ -2065,9 +2073,9 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        revs.max_parents = 1;
 
        if (add_pending_commit(head, &revs, 0))
-               die(_("Unknown commit %s"), head);
+               die(_("unknown commit %s"), head);
        if (add_pending_commit(upstream, &revs, UNINTERESTING))
-               die(_("Unknown commit %s"), upstream);
+               die(_("unknown commit %s"), upstream);
 
        /* Don't say anything if head and upstream are the same. */
        if (revs.pending.nr == 2) {
@@ -2079,7 +2087,7 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        get_patch_ids(&revs, &ids);
 
        if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
-               die(_("Unknown commit %s"), limit);
+               die(_("unknown commit %s"), limit);
 
        /* reverse the list of commits */
        if (prepare_revision_walk(&revs))
index 1ec9ddd751df6644d2c39ace41a1494800082638..97613eccb54dcba31d9fb35df54673fdf1f57817 100644 (file)
@@ -31,16 +31,39 @@ static int prune_tmp_file(const char *fullpath)
        return 0;
 }
 
+static void perform_reachability_traversal(struct rev_info *revs)
+{
+       static int initialized;
+       struct progress *progress = NULL;
+
+       if (initialized)
+               return;
+
+       if (show_progress)
+               progress = start_delayed_progress(_("Checking connectivity"), 0);
+       mark_reachable_objects(revs, 1, expire, progress);
+       stop_progress(&progress);
+       initialized = 1;
+}
+
+static int is_object_reachable(const struct object_id *oid,
+                              struct rev_info *revs)
+{
+       struct object *obj;
+
+       perform_reachability_traversal(revs);
+
+       obj = lookup_object(the_repository, oid->hash);
+       return obj && (obj->flags & SEEN);
+}
+
 static int prune_object(const struct object_id *oid, const char *fullpath,
                        void *data)
 {
+       struct rev_info *revs = data;
        struct stat st;
 
-       /*
-        * Do we know about this object?
-        * It must have been reachable
-        */
-       if (lookup_object(the_repository, oid->hash))
+       if (is_object_reachable(oid, revs))
                return 0;
 
        if (lstat(fullpath, &st)) {
@@ -102,7 +125,6 @@ static void remove_temporary_files(const char *path)
 int cmd_prune(int argc, const char **argv, const char *prefix)
 {
        struct rev_info revs;
-       struct progress *progress = NULL;
        int exclude_promisor_objects = 0;
        const struct option options[] = {
                OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
@@ -142,17 +164,13 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
 
        if (show_progress == -1)
                show_progress = isatty(2);
-       if (show_progress)
-               progress = start_delayed_progress(_("Checking connectivity"), 0);
        if (exclude_promisor_objects) {
                fetch_if_missing = 0;
                revs.exclude_promisor_objects = 1;
        }
 
-       mark_reachable_objects(&revs, 1, expire, progress);
-       stop_progress(&progress);
        for_each_loose_file_in_objdir(get_object_directory(), prune_object,
-                                     prune_cruft, prune_subdir, NULL);
+                                     prune_cruft, prune_subdir, &revs);
 
        prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
        remove_temporary_files(get_object_directory());
@@ -160,8 +178,10 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
        remove_temporary_files(s);
        free(s);
 
-       if (is_repository_shallow(the_repository))
+       if (is_repository_shallow(the_repository)) {
+               perform_reachability_traversal(&revs);
                prune_shallow(show_only ? PRUNE_SHOW_ONLY : 0);
+       }
 
        return 0;
 }
index 701d1473dc59e018247f337d37f00fe04f83cb98..33db889955402168f95083d741d4094db89cb503 100644 (file)
@@ -56,6 +56,10 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
                return REBASE_MERGES;
        else if (!strcmp(value, "interactive") || !strcmp(value, "i"))
                return REBASE_INTERACTIVE;
+       /*
+        * Please update _git_config() in git-completion.bash when you
+        * add new rebase modes.
+        */
 
        if (fatal)
                die(_("Invalid value for %s: %s"), key, value);
index 52114cbf0d9f98d52a5b48d8806019d14b1c7029..2e41ad5644c11db0d496aa3c8374cc194b331e78 100644 (file)
@@ -46,29 +46,6 @@ enum rebase_type {
        REBASE_PRESERVE_MERGES
 };
 
-static int use_builtin_rebase(void)
-{
-       struct child_process cp = CHILD_PROCESS_INIT;
-       struct strbuf out = STRBUF_INIT;
-       int ret, env = git_env_bool("GIT_TEST_REBASE_USE_BUILTIN", -1);
-
-       if (env != -1)
-               return env;
-
-       argv_array_pushl(&cp.args,
-                        "config", "--bool", "rebase.usebuiltin", NULL);
-       cp.git_cmd = 1;
-       if (capture_command(&cp, &out, 6)) {
-               strbuf_release(&out);
-               return 1;
-       }
-
-       strbuf_trim(&out);
-       ret = !strcmp("true", out.buf);
-       strbuf_release(&out);
-       return ret;
-}
-
 struct rebase_options {
        enum rebase_type type;
        const char *state_dir;
@@ -106,6 +83,7 @@ struct rebase_options {
        char *strategy, *strategy_opts;
        struct strbuf git_format_patch_opt;
        int reschedule_failed_exec;
+       int use_legacy_rebase;
 };
 
 static int is_interactive(struct rebase_options *opts)
@@ -369,6 +347,7 @@ static void add_var(struct strbuf *buf, const char *name, const char *value)
 #define RESET_HEAD_HARD (1<<1)
 #define RESET_HEAD_RUN_POST_CHECKOUT_HOOK (1<<2)
 #define RESET_HEAD_REFS_ONLY (1<<3)
+#define RESET_ORIG_HEAD (1<<4)
 
 static int reset_head(struct object_id *oid, const char *action,
                      const char *switch_to_branch, unsigned flags,
@@ -378,6 +357,7 @@ static int reset_head(struct object_id *oid, const char *action,
        unsigned reset_hard = flags & RESET_HEAD_HARD;
        unsigned run_hook = flags & RESET_HEAD_RUN_POST_CHECKOUT_HOOK;
        unsigned refs_only = flags & RESET_HEAD_REFS_ONLY;
+       unsigned update_orig_head = flags & RESET_ORIG_HEAD;
        struct object_id head_oid;
        struct tree_desc desc[2] = { { NULL }, { NULL } };
        struct lock_file lock = LOCK_INIT;
@@ -454,18 +434,21 @@ static int reset_head(struct object_id *oid, const char *action,
        strbuf_addf(&msg, "%s: ", reflog_action ? reflog_action : "rebase");
        prefix_len = msg.len;
 
-       if (!get_oid("ORIG_HEAD", &oid_old_orig))
-               old_orig = &oid_old_orig;
-       if (!get_oid("HEAD", &oid_orig)) {
-               orig = &oid_orig;
-               if (!reflog_orig_head) {
-                       strbuf_addstr(&msg, "updating ORIG_HEAD");
-                       reflog_orig_head = msg.buf;
-               }
-               update_ref(reflog_orig_head, "ORIG_HEAD", orig, old_orig, 0,
-                          UPDATE_REFS_MSG_ON_ERR);
-       } else if (old_orig)
-               delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
+       if (update_orig_head) {
+               if (!get_oid("ORIG_HEAD", &oid_old_orig))
+                       old_orig = &oid_old_orig;
+               if (!get_oid("HEAD", &oid_orig)) {
+                       orig = &oid_orig;
+                       if (!reflog_orig_head) {
+                               strbuf_addstr(&msg, "updating ORIG_HEAD");
+                               reflog_orig_head = msg.buf;
+                       }
+                       update_ref(reflog_orig_head, "ORIG_HEAD", orig,
+                                  old_orig, 0, UPDATE_REFS_MSG_ON_ERR);
+               } else if (old_orig)
+                       delete_ref(NULL, "ORIG_HEAD", old_orig, 0);
+       }
+
        if (!reflog_head) {
                strbuf_setlen(&msg, prefix_len);
                strbuf_addstr(&msg, "updating HEAD");
@@ -476,7 +459,7 @@ static int reset_head(struct object_id *oid, const char *action,
                                 detach_head ? REF_NO_DEREF : 0,
                                 UPDATE_REFS_MSG_ON_ERR);
        else {
-               ret = update_ref(reflog_orig_head, switch_to_branch, oid,
+               ret = update_ref(reflog_head, switch_to_branch, oid,
                                 NULL, 0, UPDATE_REFS_MSG_ON_ERR);
                if (!ret)
                        ret = create_symref("HEAD", switch_to_branch,
@@ -869,6 +852,11 @@ static int rebase_config(const char *var, const char *value, void *data)
                return 0;
        }
 
+       if (!strcmp(var, "rebase.usebuiltin")) {
+               opts->use_legacy_rebase = !git_config_bool(var, value);
+               return 0;
+       }
+
        return git_default_config(var, value, data);
 }
 
@@ -1100,8 +1088,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        PARSE_OPT_NOARG | PARSE_OPT_NONEG,
                        parse_opt_interactive },
                OPT_SET_INT('p', "preserve-merges", &options.type,
-                           N_("try to recreate merges instead of ignoring "
-                              "them"), REBASE_PRESERVE_MERGES),
+                           N_("(DEPRECATED) try to recreate merges instead of "
+                              "ignoring them"), REBASE_PRESERVE_MERGES),
                OPT_BOOL(0, "rerere-autoupdate",
                         &options.allow_rerere_autoupdate,
                         N_("allow rerere to update index with resolved "
@@ -1143,22 +1131,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        };
        int i;
 
-       /*
-        * NEEDSWORK: Once the builtin rebase has been tested enough
-        * and git-legacy-rebase.sh is retired to contrib/, this preamble
-        * can be removed.
-        */
-
-       if (!use_builtin_rebase()) {
-               const char *path = mkpath("%s/git-legacy-rebase",
-                                         git_exec_path());
-
-               if (sane_execvp(path, (char **)argv) < 0)
-                       die_errno(_("could not exec %s"), path);
-               else
-                       BUG("sane_execvp() returned???");
-       }
-
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
@@ -1169,6 +1141,11 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
 
        git_config(rebase_config, &options);
 
+       if (options.use_legacy_rebase ||
+           !git_env_bool("GIT_TEST_REBASE_USE_BUILTIN", -1))
+               warning(_("the rebase.useBuiltin support has been removed!\n"
+                         "See its entry in 'git help config' for details."));
+
        strbuf_reset(&buf);
        strbuf_addf(&buf, "%s/applying", apply_dir());
        if(file_exists(buf.buf))
@@ -1212,6 +1189,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                usage_with_options(builtin_rebase_usage,
                                   builtin_rebase_options);
 
+       if (options.type == REBASE_PRESERVE_MERGES)
+               warning(_("git rebase --preserve-merges is deprecated. "
+                         "Use --rebase-merges instead."));
+
        if (action != NO_ACTION && !in_progress)
                die(_("No rebase in progress?"));
        setenv(GIT_REFLOG_ACTION_ENVIRONMENT, "rebase", 0);
@@ -1777,7 +1758,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        strbuf_addf(&msg, "%s: checkout %s",
                    getenv(GIT_REFLOG_ACTION_ENVIRONMENT), options.onto_name);
        if (reset_head(&options.onto->object.oid, "checkout", NULL,
-                      RESET_HEAD_DETACH | RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
+                      RESET_HEAD_DETACH | RESET_ORIG_HEAD | 
+                      RESET_HEAD_RUN_POST_CHECKOUT_HOOK,
                       NULL, msg.buf))
                die(_("Could not detach HEAD"));
        strbuf_release(&msg);
@@ -1793,8 +1775,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                strbuf_addf(&msg, "rebase finished: %s onto %s",
                        options.head_name ? options.head_name : "detached HEAD",
                        oid_to_hex(&options.onto->object.oid));
-               reset_head(NULL, "Fast-forwarded", options.head_name, 0,
-                          "HEAD", msg.buf);
+               reset_head(NULL, "Fast-forwarded", options.head_name,
+                          RESET_HEAD_REFS_ONLY, "HEAD", msg.buf);
                strbuf_release(&msg);
                ret = !!finish_rebase(&options);
                goto cleanup;
index 8bc714a5fc30e13cff98dc7ff7e68578b4842863..29f165d8bd3513a6f85667b070e8f157994364bb 100644 (file)
@@ -1202,17 +1202,12 @@ static void run_update_post_hook(struct command *commands)
        }
 }
 
-static void check_aliased_update(struct command *cmd, struct string_list *list)
+static void check_aliased_update_internal(struct command *cmd,
+                                         struct string_list *list,
+                                         const char *dst_name, int flag)
 {
-       struct strbuf buf = STRBUF_INIT;
-       const char *dst_name;
        struct string_list_item *item;
        struct command *dst_cmd;
-       int flag;
-
-       strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
-       dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
-       strbuf_release(&buf);
 
        if (!(flag & REF_ISSYMREF))
                return;
@@ -1251,6 +1246,18 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
                "inconsistent aliased update";
 }
 
+static void check_aliased_update(struct command *cmd, struct string_list *list)
+{
+       struct strbuf buf = STRBUF_INIT;
+       const char *dst_name;
+       int flag;
+
+       strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
+       dst_name = resolve_ref_unsafe(buf.buf, 0, NULL, &flag);
+       check_aliased_update_internal(cmd, list, dst_name, flag);
+       strbuf_release(&buf);
+}
+
 static void check_aliased_updates(struct command *commands)
 {
        struct command *cmd;
index 5b80b7f21141d6f85d8444d669dffe289f3a60f5..f5701629a8a5698a64c91ca92226e6da72697441 100644 (file)
@@ -82,6 +82,10 @@ static int list_replace_refs(const char *pattern, const char *format)
                data.format = REPLACE_FORMAT_MEDIUM;
        else if (!strcmp(format, "long"))
                data.format = REPLACE_FORMAT_LONG;
+       /*
+        * Please update _git_replace() in git-completion.bash when
+        * you add new format
+        */
        else
                return error(_("invalid replace format '%s'\n"
                               "valid formats are 'short', 'medium' and 'long'"),
index 5b5b6dbb1c9b6f9893f3d0420c99655eb19501a8..425a5774db0697774df499fc16a626ab1e1efcf9 100644 (file)
@@ -238,7 +238,7 @@ static inline void finish_object__ma(struct object *obj)
 static int finish_object(struct object *obj, const char *name, void *cb_data)
 {
        struct rev_list_info *info = cb_data;
-       if (!has_object_file(&obj->oid)) {
+       if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
                finish_object__ma(obj);
                return 1;
        }
index 6cc094a453806308442d054a7d1c073ecf18b87b..d2a7e2f3f18ba411d065a52ac868db612de5beaa 100644 (file)
@@ -268,10 +268,10 @@ static int add_worktree(const char *path, const char *refname,
        struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
        struct strbuf sb = STRBUF_INIT;
        const char *name;
-       struct stat st;
        struct child_process cp = CHILD_PROCESS_INIT;
        struct argv_array child_env = ARGV_ARRAY_INIT;
-       int counter = 0, len, ret;
+       unsigned int counter = 0;
+       int len, ret;
        struct strbuf symref = STRBUF_INIT;
        struct commit *commit = NULL;
        int is_branch = 0;
@@ -295,8 +295,12 @@ static int add_worktree(const char *path, const char *refname,
        if (safe_create_leading_directories_const(sb_repo.buf))
                die_errno(_("could not create leading directories of '%s'"),
                          sb_repo.buf);
-       while (!stat(sb_repo.buf, &st)) {
+
+       while (mkdir(sb_repo.buf, 0777)) {
                counter++;
+               if ((errno != EEXIST) || !counter /* overflow */)
+                       die_errno(_("could not create directory of '%s'"),
+                                 sb_repo.buf);
                strbuf_setlen(&sb_repo, len);
                strbuf_addf(&sb_repo, "%d", counter);
        }
@@ -306,8 +310,6 @@ static int add_worktree(const char *path, const char *refname,
        atexit(remove_junk);
        sigchain_push_common(remove_junk_on_signal);
 
-       if (mkdir(sb_repo.buf, 0777))
-               die_errno(_("could not create directory of '%s'"), sb_repo.buf);
        junk_git_dir = xstrdup(sb_repo.buf);
        is_junk = 1;
 
diff --git a/cache.h b/cache.h
index abd518a9a23394fd47b572c6957c712abac139a2..ac92421f3a8bc814da3f01731f2d8d8a52dc8364 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -962,6 +962,10 @@ extern char *repository_format_partial_clone;
 extern const char *core_partial_clone_filter_default;
 extern int repository_format_worktree_config;
 
+/*
+ * You _have_ to initialize a `struct repository_format` using
+ * `= REPOSITORY_FORMAT_INIT` before calling `read_repository_format()`.
+ */
 struct repository_format {
        int version;
        int precious_objects;
@@ -973,14 +977,35 @@ struct repository_format {
        struct string_list unknown_extensions;
 };
 
+/*
+ * Always use this to initialize a `struct repository_format`
+ * to a well-defined, default state before calling
+ * `read_repository()`.
+ */
+#define REPOSITORY_FORMAT_INIT \
+{ \
+       .version = -1, \
+       .is_bare = -1, \
+       .hash_algo = GIT_HASH_SHA1, \
+       .unknown_extensions = STRING_LIST_INIT_DUP, \
+}
+
 /*
  * Read the repository format characteristics from the config file "path" into
- * "format" struct. Returns the numeric version. On error, -1 is returned,
- * format->version is set to -1, and all other fields in the struct are
- * undefined.
+ * "format" struct. Returns the numeric version. On error, or if no version is
+ * found in the configuration, -1 is returned, format->version is set to -1,
+ * and all other fields in the struct are set to the default configuration
+ * (REPOSITORY_FORMAT_INIT). Always initialize the struct using
+ * REPOSITORY_FORMAT_INIT before calling this function.
  */
 int read_repository_format(struct repository_format *format, const char *path);
 
+/*
+ * Free the memory held onto by `format`, but not the struct itself.
+ * (No need to use this after `read_repository_format()` fails.)
+ */
+void clear_repository_format(struct repository_format *format);
+
 /*
  * Verify that the repository described by repository_format is something we
  * can read. If it is, return 0. Otherwise, return -1, and "err" will describe
diff --git a/check-racy.c b/check-racy.c
deleted file mode 100644 (file)
index 24b6542..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "cache.h"
-
-int main(int ac, char **av)
-{
-       int i;
-       int dirty, clean, racy;
-
-       dirty = clean = racy = 0;
-       read_cache();
-       for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = active_cache[i];
-               struct stat st;
-
-               if (lstat(ce->name, &st)) {
-                       error_errno("lstat(%s)", ce->name);
-                       continue;
-               }
-
-               if (ce_match_stat(ce, &st, 0))
-                       dirty++;
-               else if (ce_match_stat(ce, &st, CE_MATCH_RACY_IS_DIRTY))
-                       racy++;
-               else
-                       clean++;
-       }
-       printf("dirty %d, clean %d, racy %d\n", dirty, clean, racy);
-       return 0;
-}
diff --git a/ci/run-windows-build.sh b/ci/run-windows-build.sh
deleted file mode 100755 (executable)
index a73a4ec..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env bash
-#
-# Script to trigger the Git for Windows build and test run.
-# Set the $GFW_CI_TOKEN as environment variable.
-# Pass the branch (only branches on https://github.com/git/git are
-# supported) and a commit hash.
-#
-
-. ${0%/*}/lib.sh
-
-test $# -ne 2 && echo "Unexpected number of parameters" && exit 1
-test -z "$GFW_CI_TOKEN" && echo "GFW_CI_TOKEN not defined" && exit
-
-BRANCH=$1
-COMMIT=$2
-
-gfwci () {
-       local CURL_ERROR_CODE HTTP_CODE
-       CONTENT_FILE=$(mktemp -t "git-windows-ci-XXXXXX")
-       while test -z $HTTP_CODE
-       do
-       HTTP_CODE=$(curl \
-               -H "Authentication: Bearer $GFW_CI_TOKEN" \
-               --silent --retry 5 --write-out '%{HTTP_CODE}' \
-               --output >(sed "$(printf '1s/^\xef\xbb\xbf//')" >$CONTENT_FILE) \
-               "https://git-for-windows-ci.azurewebsites.net/api/TestNow?$1" \
-       )
-       CURL_ERROR_CODE=$?
-               # The GfW CI web app sometimes returns HTTP errors of
-               # "502 bad gateway" or "503 service unavailable".
-               # We also need to check the HTTP content because the GfW web
-               # app seems to pass through (error) results from other Azure
-               # calls with HTTP code 200.
-               # Wait a little and retry if we detect this error. More info:
-               # https://docs.microsoft.com/en-in/azure/app-service-web/app-service-web-troubleshoot-http-502-http-503
-               if test $HTTP_CODE -eq 502 ||
-                  test $HTTP_CODE -eq 503 ||
-                  grep "502 - Web server received an invalid response" $CONTENT_FILE >/dev/null
-               then
-                       sleep 10
-                       HTTP_CODE=
-               fi
-       done
-       cat $CONTENT_FILE
-       rm $CONTENT_FILE
-       if test $CURL_ERROR_CODE -ne 0
-       then
-               return $CURL_ERROR_CODE
-       fi
-       if test "$HTTP_CODE" -ge 400 && test "$HTTP_CODE" -lt 600
-       then
-               return 127
-       fi
-}
-
-# Trigger build job
-BUILD_ID=$(gfwci "action=trigger&branch=$BRANCH&commit=$COMMIT&skipTests=false")
-if test $? -ne 0
-then
-       echo "Unable to trigger Visual Studio Team Services Build"
-       echo "$BUILD_ID"
-       exit 1
-fi
-
-# Check if the $BUILD_ID contains a number
-case $BUILD_ID in
-''|*[!0-9]*) echo "Unexpected build number: $BUILD_ID" && exit 1
-esac
-
-echo "Visual Studio Team Services Build #${BUILD_ID}"
-
-# Tracing execued commands would produce too much noise in the waiting
-# loop below.
-set +x
-
-# Wait until build job finished
-STATUS=
-RESULT=
-while true
-do
-       LAST_STATUS=$STATUS
-       STATUS=$(gfwci "action=status&buildId=$BUILD_ID")
-       test "$STATUS" = "$LAST_STATUS" || printf "\nStatus: %s " "$STATUS"
-       printf "."
-
-       case "$STATUS" in
-       inProgress|postponed|notStarted) sleep 10               ;; # continue
-                "completed: succeeded") RESULT="success"; break;; # success
-                   "completed: failed")                   break;; # failure
-       *) echo "Unhandled status: $STATUS";               break;; # unknown
-       esac
-done
-
-# Print log
-echo ""
-echo ""
-set -x
-gfwci "action=log&buildId=$BUILD_ID" | cut -c 30-
-
-# Set exit code for TravisCI
-test "$RESULT" = "success"
-
-save_good_tree
index 5078ce5eccfaf17620c21e0a7f7133b3badef3d3..e4e25735ceb332e0a3c3601ba36b07bb933c7ba5 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef COMPAT_BSWAP_H
+#define COMPAT_BSWAP_H
+
 /*
  * Let's make sure we always have a sane definition for ntohl()/htonl().
  * Some libraries define those as a function call, just to perform byte
@@ -210,3 +213,5 @@ static inline void put_be64(void *ptr, uint64_t value)
 }
 
 #endif
+
+#endif /* COMPAT_BSWAP_H */
index 7354fe15b3d93737b1c15c74943da2b7630108d6..bf1f3fcdeed3a819b7098baf1d710be29f16c93e 100644 (file)
@@ -1,41 +1,41 @@
 ifeq ($(filter no-error,$(DEVOPTS)),)
-CFLAGS += -Werror
+DEVELOPER_CFLAGS += -Werror
 endif
 ifneq ($(filter pedantic,$(DEVOPTS)),)
-CFLAGS += -pedantic
+DEVELOPER_CFLAGS += -pedantic
 # don't warn for each N_ use
-CFLAGS += -DUSE_PARENS_AROUND_GETTEXT_N=0
-endif
-CFLAGS += -Wall
-CFLAGS += -Wdeclaration-after-statement
-CFLAGS += -Wformat-security
-CFLAGS += -Wno-format-zero-length
-CFLAGS += -Wold-style-definition
-CFLAGS += -Woverflow
-CFLAGS += -Wpointer-arith
-CFLAGS += -Wstrict-prototypes
-CFLAGS += -Wunused
-CFLAGS += -Wvla
+DEVELOPER_CFLAGS += -DUSE_PARENS_AROUND_GETTEXT_N=0
+endif
+DEVELOPER_CFLAGS += -Wall
+DEVELOPER_CFLAGS += -Wdeclaration-after-statement
+DEVELOPER_CFLAGS += -Wformat-security
+DEVELOPER_CFLAGS += -Wno-format-zero-length
+DEVELOPER_CFLAGS += -Wold-style-definition
+DEVELOPER_CFLAGS += -Woverflow
+DEVELOPER_CFLAGS += -Wpointer-arith
+DEVELOPER_CFLAGS += -Wstrict-prototypes
+DEVELOPER_CFLAGS += -Wunused
+DEVELOPER_CFLAGS += -Wvla
 
 ifndef COMPILER_FEATURES
 COMPILER_FEATURES := $(shell ./detect-compiler $(CC))
 endif
 
 ifneq ($(filter clang4,$(COMPILER_FEATURES)),)
-CFLAGS += -Wtautological-constant-out-of-range-compare
+DEVELOPER_CFLAGS += -Wtautological-constant-out-of-range-compare
 endif
 
 ifneq ($(or $(filter gcc6,$(COMPILER_FEATURES)),$(filter clang4,$(COMPILER_FEATURES))),)
-CFLAGS += -Wextra
+DEVELOPER_CFLAGS += -Wextra
 # if a function is public, there should be a prototype and the right
 # header file should be included. If not, it should be static.
-CFLAGS += -Wmissing-prototypes
+DEVELOPER_CFLAGS += -Wmissing-prototypes
 ifeq ($(filter extra-all,$(DEVOPTS)),)
 # These are disabled because we have these all over the place.
-CFLAGS += -Wno-empty-body
-CFLAGS += -Wno-missing-field-initializers
-CFLAGS += -Wno-sign-compare
-CFLAGS += -Wno-unused-parameter
+DEVELOPER_CFLAGS += -Wno-empty-body
+DEVELOPER_CFLAGS += -Wno-missing-field-initializers
+DEVELOPER_CFLAGS += -Wno-sign-compare
+DEVELOPER_CFLAGS += -Wno-unused-parameter
 endif
 endif
 
@@ -43,6 +43,6 @@ endif
 # not worth fixing since newer compilers correctly stop complaining
 ifneq ($(filter gcc4,$(COMPILER_FEATURES)),)
 ifeq ($(filter gcc5,$(COMPILER_FEATURES)),)
-CFLAGS += -Wno-uninitialized
+DEVELOPER_CFLAGS += -Wno-uninitialized
 endif
 endif
index c8b0e34c3144da9ac384a56b1d2903d4d9e70ec9..41e85fab1c8d1ed5b6b7ffdbe8b840bdc12d77de 100644 (file)
@@ -530,7 +530,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        NO_STRTOUMAX = YesPlease
        NO_MKDTEMP = YesPlease
        NO_SVN_TESTS = YesPlease
-       NO_PERL_MAKEMAKER = YesPlease
        RUNTIME_PREFIX = YesPlease
        HAVE_WPGMPTR = YesWeDo
        NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
@@ -569,7 +568,7 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
        NO_GETTEXT = YesPlease
        COMPAT_CLFAGS += -D__USE_MINGW_ACCESS
 else
-       ifeq ($(shell expr "$(uname_R)" : '2\.'),2)
+       ifneq ($(shell expr "$(uname_R)" : '1\.'),2)
                # MSys2
                prefix = /usr/
                ifeq (MINGW32,$(MSYSTEM))
index de56879960d5224437e60d81c3e990ac7ed97a18..93b5e972cb633fe6dd9009d05acbb7be0c976294 100644 (file)
@@ -853,6 +853,11 @@ __git_compute_merge_strategies ()
        __git_merge_strategies=$(__git_list_merge_strategies)
 }
 
+__git_merge_strategy_options="ours theirs subtree subtree= patience
+       histogram diff-algorithm= ignore-space-change ignore-all-space
+       ignore-space-at-eol renormalize no-renormalize no-renames
+       find-renames find-renames= rename-threshold="
+
 __git_complete_revlist_file ()
 {
        local dequoted_word pfx ls ref cur_="$cur"
@@ -996,12 +1001,21 @@ __git_complete_strategy ()
        -s|--strategy)
                __gitcomp "$__git_merge_strategies"
                return 0
+               ;;
+       -X)
+               __gitcomp "$__git_merge_strategy_options"
+               return 0
+               ;;
        esac
        case "$cur" in
        --strategy=*)
                __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
                return 0
                ;;
+       --strategy-option=*)
+               __gitcomp "$__git_merge_strategy_options" "" "${cur##--strategy-option=}"
+               return 0
+               ;;
        esac
        return 1
 }
@@ -1010,7 +1024,7 @@ __git_all_commands=
 __git_compute_all_commands ()
 {
        test -n "$__git_all_commands" ||
-       __git_all_commands=$(git --list-cmds=main,others,alias,nohelpers)
+       __git_all_commands=$(__git --list-cmds=main,others,alias,nohelpers)
 }
 
 # Lists all set config variables starting with the given section prefix,
@@ -1163,6 +1177,7 @@ __git_count_arguments ()
 }
 
 __git_whitespacelist="nowarn warn error error-all fix"
+__git_patchformat="mbox stgit stgit-series hg mboxrd"
 __git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
 
 _git_am ()
@@ -1177,6 +1192,10 @@ _git_am ()
                __gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
                return
                ;;
+       --patch-format=*)
+               __gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
+               return
+               ;;
        --*)
                __gitcomp_builtin am "" \
                        "$__git_am_inprogress_options"
@@ -1200,6 +1219,10 @@ _git_apply ()
 _git_add ()
 {
        case "$cur" in
+       --chmod=*)
+               __gitcomp "+x -x" "" "${cur##--chmod=}"
+               return
+               ;;
        --*)
                __gitcomp_builtin add
                return
@@ -1260,6 +1283,8 @@ _git_bisect ()
        esac
 }
 
+__git_ref_fieldlist="refname objecttype objectsize objectname upstream push HEAD symref"
+
 _git_branch ()
 {
        local i c=1 only_local_ref="n" has_r="n"
@@ -1343,6 +1368,9 @@ _git_cherry_pick ()
                __gitcomp "$__git_cherry_pick_inprogress_options"
                return
        fi
+
+       __git_complete_strategy && return
+
        case "$cur" in
        --*)
                __gitcomp_builtin cherry-pick "" \
@@ -1506,6 +1534,10 @@ _git_fetch ()
                __gitcomp "$__git_fetch_recurse_submodules" "" "${cur##--recurse-submodules=}"
                return
                ;;
+       --filter=*)
+               __gitcomp "blob:none blob:limit= sparse:oid= sparse:path=" "" "${cur##--filter=}"
+               return
+               ;;
        --*)
                __gitcomp_builtin fetch
                return
@@ -1620,9 +1652,9 @@ _git_help ()
        esac
        if test -n "$GIT_TESTING_ALL_COMMAND_LIST"
        then
-               __gitcomp "$GIT_TESTING_ALL_COMMAND_LIST $(git --list-cmds=alias,list-guide) gitk"
+               __gitcomp "$GIT_TESTING_ALL_COMMAND_LIST $(__git --list-cmds=alias,list-guide) gitk"
        else
-               __gitcomp "$(git --list-cmds=main,nohelpers,alias,list-guide) gitk"
+               __gitcomp "$(__git --list-cmds=main,nohelpers,alias,list-guide) gitk"
        fi
 }
 
@@ -1702,8 +1734,8 @@ __git_log_shortlog_options="
        --all-match --invert-grep
 "
 
-__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_pretty_formats="oneline short medium full fuller email raw format: mboxrd"
+__git_log_date_formats="relative iso8601 iso8601-strict rfc2822 short local default raw unix format:"
 
 _git_log ()
 {
@@ -2221,7 +2253,7 @@ _git_config ()
                return
                ;;
        diff.submodule)
-               __gitcomp "log short"
+               __gitcomp "$__git_diff_submodule_formats"
                return
                ;;
        help.format)
@@ -2388,6 +2420,10 @@ _git_remote ()
 _git_replace ()
 {
        case "$cur" in
+       --format=*)
+               __gitcomp "short medium long" "" "${cur##--format=}"
+               return
+               ;;
        --*)
                __gitcomp_builtin replace
                return
@@ -2429,6 +2465,7 @@ _git_revert ()
                __gitcomp "$__git_revert_inprogress_options"
                return
        fi
+       __git_complete_strategy && return
        case "$cur" in
        --*)
                __gitcomp_builtin revert "" \
@@ -2888,7 +2925,7 @@ __git_main ()
                        then
                                __gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
                        else
-                               __gitcomp "$(git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+                               __gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
                        fi
                        ;;
                esac
index 147201dc6c5786c9cfedbbbff0df0b1dced171db..868e18b9a1ab85ae093da936558d394b37059215 100755 (executable)
@@ -14,7 +14,7 @@ git subtree add   --prefix=<prefix> <repository> <ref>
 git subtree merge --prefix=<prefix> <commit>
 git subtree pull  --prefix=<prefix> <repository> <ref>
 git subtree push  --prefix=<prefix> <repository> <ref>
-git subtree split --prefix=<prefix> <commit...>
+git subtree split --prefix=<prefix> <commit>
 --
 h,help        show the help
 q             quiet
@@ -77,6 +77,12 @@ assert () {
        fi
 }
 
+ensure_single_rev () {
+       if test $# -ne 1
+       then
+               die "You must provide exactly one revision.  Got: '$@'"
+       fi
+}
 
 while test $# -gt 0
 do
@@ -185,6 +191,7 @@ if test "$command" != "pull" &&
 then
        revs=$(git rev-parse $default --revs-only "$@") || exit $?
        dirs=$(git rev-parse --no-revs --no-flags "$@") || exit $?
+       ensure_single_rev $revs
        if test -n "$dirs"
        then
                die "Error: Use --prefix instead of bare filenames."
@@ -716,9 +723,8 @@ cmd_add_repository () {
 }
 
 cmd_add_commit () {
-       revs=$(git rev-parse $default --revs-only "$@") || exit $?
-       set -- $revs
-       rev="$1"
+       rev=$(git rev-parse $default --revs-only "$@") || exit $?
+       ensure_single_rev $rev
 
        debug "Adding $dir as '$rev'..."
        git read-tree --prefix="$dir" $rev || exit $?
@@ -817,16 +823,10 @@ cmd_split () {
 }
 
 cmd_merge () {
-       revs=$(git rev-parse $default --revs-only "$@") || exit $?
+       rev=$(git rev-parse $default --revs-only "$@") || exit $?
+       ensure_single_rev $rev
        ensure_clean
 
-       set -- $revs
-       if test $# -ne 1
-       then
-               die "You must provide exactly one revision.  Got: '$revs'"
-       fi
-       rev="$1"
-
        if test -n "$squash"
        then
                first_split="$(find_latest_squash "$dir")"
index 5d0307fc1004f215c48a6f653e21da41bee71baa..94ff8376492257782a1af5b3d2851ee8724c2edd 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -731,7 +731,7 @@ static int apply_single_file_filter(const char *path, const char *src, size_t le
        if (start_async(&async))
                return 0;       /* error was already reported */
 
-       if (strbuf_read(&nbuf, async.out, len) < 0) {
+       if (strbuf_read(&nbuf, async.out, 0) < 0) {
                err = error(_("read from external filter '%s' failed"), cmd);
        }
        if (close(async.out)) {
diff --git a/date.c b/date.c
index 9c5870e102951ed25f5def2103dab15bf8ed5c99..8126146c5069c9ab9d9f25f1f1bba1323f63cf52 100644 (file)
--- a/date.c
+++ b/date.c
@@ -921,6 +921,10 @@ static enum date_mode_type parse_date_type(const char *format, const char **end)
                return DATE_UNIX;
        if (skip_prefix(format, "format", end))
                return DATE_STRFTIME;
+       /*
+        * Please update $__git_log_date_formats in
+        * git-completion.bash when you add new formats.
+        */
 
        die("unknown date format %s", format);
 }
index 23c8d351b3aa5912c49c9da0eecd8727cf06ac72..a838c219ec044b9fb78b4bda058d078e66d7aaf8 100644 (file)
@@ -531,7 +531,7 @@ int run_diff_index(struct rev_info *revs, int cached)
                exit(128);
 
        diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/");
-       diffcore_fix_diff_index(&revs->diffopt);
+       diffcore_fix_diff_index();
        diffcore_std(&revs->diffopt);
        diff_flush(&revs->diffopt);
        trace_performance_leave("diff-index");
index 9414e922d164e96ffedfa2504045930b058dbc80..6001baecd4c61ae22dd0aaec11bd4bc48a9152f8 100644 (file)
@@ -233,8 +233,7 @@ static void fixup_paths(const char **path, struct strbuf *replacement)
        }
 }
 
-void diff_no_index(struct repository *r,
-                  struct rev_info *revs,
+void diff_no_index(struct rev_info *revs,
                   int argc, const char **argv)
 {
        int i;
@@ -242,11 +241,6 @@ void diff_no_index(struct repository *r,
        struct strbuf replacement = STRBUF_INIT;
        const char *prefix = revs->prefix;
 
-       /*
-        * FIXME: --no-index should not look at index and we should be
-        * able to pass NULL repo. Maybe later.
-        */
-       repo_diff_setup(r, &revs->diffopt);
        for (i = 1; i < argc - 2; ) {
                int j;
                if (!strcmp(argv[i], "--no-index"))
diff --git a/diff.c b/diff.c
index 1a1f21578766e5fa6c455c94cce358ccad5de1d1..6dfad79f1d67e9659eaaa207bf7a3e7c6a596a6b 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -104,11 +104,6 @@ static const char *color_diff_slots[] = {
        [DIFF_FILE_NEW_BOLD]          = "newBold",
 };
 
-static NORETURN void die_want_option(const char *option_name)
-{
-       die(_("option '%s' requires a value"), option_name);
-}
-
 define_list_config_array_extra(color_diff_slots, {"plain"});
 
 static int parse_diff_color_slot(const char *var)
@@ -179,6 +174,10 @@ static int parse_submodule_params(struct diff_options *options, const char *valu
                options->submodule_format = DIFF_SUBMODULE_SHORT;
        else if (!strcmp(value, "diff"))
                options->submodule_format = DIFF_SUBMODULE_INLINE_DIFF;
+       /*
+        * Please update $__git_diff_submodule_formats in
+        * git-completion.bash when you add new formats.
+        */
        else
                return -1;
        return 0;
@@ -205,6 +204,10 @@ long parse_algorithm_value(const char *value)
                return XDF_PATIENCE_DIFF;
        else if (!strcasecmp(value, "histogram"))
                return XDF_HISTOGRAM_DIFF;
+       /*
+        * Please update $__git_diff_algorithms in git-completion.bash
+        * when you add new algorithms.
+        */
        return -1;
 }
 
@@ -1614,8 +1617,7 @@ static int new_blank_line_at_eof(struct emit_callback *ecbdata, const char *line
        return ws_blank_line(line, len, ecbdata->ws_rule);
 }
 
-static void emit_add_line(const char *reset,
-                         struct emit_callback *ecbdata,
+static void emit_add_line(struct emit_callback *ecbdata,
                          const char *line, int len)
 {
        unsigned flags = WSEH_NEW | ecbdata->ws_rule;
@@ -1625,16 +1627,14 @@ static void emit_add_line(const char *reset,
        emit_diff_symbol(ecbdata->opt, DIFF_SYMBOL_PLUS, line, len, flags);
 }
 
-static void emit_del_line(const char *reset,
-                         struct emit_callback *ecbdata,
+static void emit_del_line(struct emit_callback *ecbdata,
                          const char *line, int len)
 {
        unsigned flags = WSEH_OLD | ecbdata->ws_rule;
        emit_diff_symbol(ecbdata->opt, DIFF_SYMBOL_MINUS, line, len, flags);
 }
 
-static void emit_context_line(const char *reset,
-                             struct emit_callback *ecbdata,
+static void emit_context_line(struct emit_callback *ecbdata,
                              const char *line, int len)
 {
        unsigned flags = WSEH_CONTEXT | ecbdata->ws_rule;
@@ -1743,7 +1743,6 @@ static void emit_rewrite_lines(struct emit_callback *ecb,
                               int prefix, const char *data, int size)
 {
        const char *endp = NULL;
-       const char *reset = diff_get_color(ecb->color_diff, DIFF_RESET);
 
        while (0 < size) {
                int len;
@@ -1752,10 +1751,10 @@ static void emit_rewrite_lines(struct emit_callback *ecb,
                len = endp ? (endp - data + 1) : size;
                if (prefix != '+') {
                        ecb->lno_in_preimage++;
-                       emit_del_line(reset, ecb, data, len);
+                       emit_del_line(ecb, data, len);
                } else {
                        ecb->lno_in_postimage++;
-                       emit_add_line(reset, ecb, data, len);
+                       emit_add_line(ecb, data, len);
                }
                size -= len;
                data += len;
@@ -2292,7 +2291,7 @@ const char *diff_line_prefix(struct diff_options *opt)
        return msgbuf->buf;
 }
 
-static unsigned long sane_truncate_line(struct emit_callback *ecb, char *line, unsigned long len)
+static unsigned long sane_truncate_line(char *line, unsigned long len)
 {
        const char *cp;
        unsigned long allot;
@@ -2326,7 +2325,6 @@ static void find_lno(const char *line, struct emit_callback *ecbdata)
 static void fn_out_consume(void *priv, char *line, unsigned long len)
 {
        struct emit_callback *ecbdata = priv;
-       const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);
        struct diff_options *o = ecbdata->opt;
 
        o->found_changes = 1;
@@ -2357,7 +2355,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
        if (line[0] == '@') {
                if (ecbdata->diff_words)
                        diff_words_flush(ecbdata);
-               len = sane_truncate_line(ecbdata, line, len);
+               len = sane_truncate_line(line, len);
                find_lno(line, ecbdata);
                emit_hunk_header(ecbdata, line, len);
                return;
@@ -2393,16 +2391,16 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
        switch (line[0]) {
        case '+':
                ecbdata->lno_in_postimage++;
-               emit_add_line(reset, ecbdata, line + 1, len - 1);
+               emit_add_line(ecbdata, line + 1, len - 1);
                break;
        case '-':
                ecbdata->lno_in_preimage++;
-               emit_del_line(reset, ecbdata, line + 1, len - 1);
+               emit_del_line(ecbdata, line + 1, len - 1);
                break;
        case ' ':
                ecbdata->lno_in_postimage++;
                ecbdata->lno_in_preimage++;
-               emit_context_line(reset, ecbdata, line + 1, len - 1);
+               emit_context_line(ecbdata, line + 1, len - 1);
                break;
        default:
                /* incomplete line at the end */
@@ -4184,7 +4182,6 @@ static void run_external_diff(const char *pgm,
                              struct diff_filespec *one,
                              struct diff_filespec *two,
                              const char *xfrm_msg,
-                             int complete_rewrite,
                              struct diff_options *o)
 {
        struct argv_array argv = ARGV_ARRAY_INIT;
@@ -4342,8 +4339,7 @@ static void run_diff_cmd(const char *pgm,
        }
 
        if (pgm) {
-               run_external_diff(pgm, name, other, one, two, xfrm_msg,
-                                 complete_rewrite, o);
+               run_external_diff(pgm, name, other, one, two, xfrm_msg, o);
                return;
        }
        if (one && two)
@@ -4688,8 +4684,6 @@ static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *va
        return 1;
 }
 
-static int diff_scoreopt_parse(const char *opt);
-
 static inline int short_opt(char opt, const char **argv,
                            const char **optarg)
 {
@@ -4727,77 +4721,56 @@ int parse_long_opt(const char *opt, const char **argv,
        return 2;
 }
 
-static int stat_opt(struct diff_options *options, const char **av)
+static int diff_opt_stat(const struct option *opt, const char *value, int unset)
 {
-       const char *arg = av[0];
-       char *end;
+       struct diff_options *options = opt->value;
        int width = options->stat_width;
        int name_width = options->stat_name_width;
        int graph_width = options->stat_graph_width;
        int count = options->stat_count;
-       int argcount = 1;
+       char *end;
 
-       if (!skip_prefix(arg, "--stat", &arg))
-               BUG("stat option does not begin with --stat: %s", arg);
-       end = (char *)arg;
+       BUG_ON_OPT_NEG(unset);
 
-       switch (*arg) {
-       case '-':
-               if (skip_prefix(arg, "-width", &arg)) {
-                       if (*arg == '=')
-                               width = strtoul(arg + 1, &end, 10);
-                       else if (!*arg && !av[1])
-                               die_want_option("--stat-width");
-                       else if (!*arg) {
-                               width = strtoul(av[1], &end, 10);
-                               argcount = 2;
-                       }
-               } else if (skip_prefix(arg, "-name-width", &arg)) {
-                       if (*arg == '=')
-                               name_width = strtoul(arg + 1, &end, 10);
-                       else if (!*arg && !av[1])
-                               die_want_option("--stat-name-width");
-                       else if (!*arg) {
-                               name_width = strtoul(av[1], &end, 10);
-                               argcount = 2;
-                       }
-               } else if (skip_prefix(arg, "-graph-width", &arg)) {
-                       if (*arg == '=')
-                               graph_width = strtoul(arg + 1, &end, 10);
-                       else if (!*arg && !av[1])
-                               die_want_option("--stat-graph-width");
-                       else if (!*arg) {
-                               graph_width = strtoul(av[1], &end, 10);
-                               argcount = 2;
-                       }
-               } else if (skip_prefix(arg, "-count", &arg)) {
-                       if (*arg == '=')
-                               count = strtoul(arg + 1, &end, 10);
-                       else if (!*arg && !av[1])
-                               die_want_option("--stat-count");
-                       else if (!*arg) {
-                               count = strtoul(av[1], &end, 10);
-                               argcount = 2;
-                       }
+       if (!strcmp(opt->long_name, "stat")) {
+               if (value) {
+                       width = strtoul(value, &end, 10);
+                       if (*end == ',')
+                               name_width = strtoul(end+1, &end, 10);
+                       if (*end == ',')
+                               count = strtoul(end+1, &end, 10);
+                       if (*end)
+                               return error(_("invalid --stat value: %s"), value);
                }
-               break;
-       case '=':
-               width = strtoul(arg+1, &end, 10);
-               if (*end == ',')
-                       name_width = strtoul(end+1, &end, 10);
-               if (*end == ',')
-                       count = strtoul(end+1, &end, 10);
-       }
+       } else if (!strcmp(opt->long_name, "stat-width")) {
+               width = strtoul(value, &end, 10);
+               if (*end)
+                       return error(_("%s expects a numerical value"),
+                                    opt->long_name);
+       } else if (!strcmp(opt->long_name, "stat-name-width")) {
+               name_width = strtoul(value, &end, 10);
+               if (*end)
+                       return error(_("%s expects a numerical value"),
+                                    opt->long_name);
+       } else if (!strcmp(opt->long_name, "stat-graph-width")) {
+               graph_width = strtoul(value, &end, 10);
+               if (*end)
+                       return error(_("%s expects a numerical value"),
+                                    opt->long_name);
+       } else if (!strcmp(opt->long_name, "stat-count")) {
+               count = strtoul(value, &end, 10);
+               if (*end)
+                       return error(_("%s expects a numerical value"),
+                                    opt->long_name);
+       } else
+               BUG("%s should not get here", opt->long_name);
 
-       /* Important! This checks all the error cases! */
-       if (*end)
-               return 0;
        options->output_format |= DIFF_FORMAT_DIFFSTAT;
        options->stat_name_width = name_width;
        options->stat_graph_width = graph_width;
        options->stat_width = width;
        options->stat_count = count;
-       return argcount;
+       return 0;
 }
 
 static int parse_dirstat_opt(struct diff_options *options, const char *params)
@@ -4815,14 +4788,6 @@ static int parse_dirstat_opt(struct diff_options *options, const char *params)
        return 1;
 }
 
-static int parse_submodule_opt(struct diff_options *options, const char *value)
-{
-       if (parse_submodule_params(options, value))
-               die(_("Failed to parse --submodule option parameter: '%s'"),
-                       value);
-       return 1;
-}
-
 static const char diff_status_letters[] = {
        DIFF_STATUS_ADDED,
        DIFF_STATUS_COPIED,
@@ -4933,6 +4898,271 @@ static int parse_objfind_opt(struct diff_options *opt, const char *arg)
        return 1;
 }
 
+static int diff_opt_anchored(const struct option *opt,
+                            const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
+       ALLOC_GROW(options->anchors, options->anchors_nr + 1,
+                  options->anchors_alloc);
+       options->anchors[options->anchors_nr++] = xstrdup(arg);
+       return 0;
+}
+
+static int diff_opt_binary(const struct option *opt,
+                          const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
+       enable_patch_output(&options->output_format);
+       options->flags.binary = 1;
+       return 0;
+}
+
+static int diff_opt_break_rewrites(const struct option *opt,
+                                  const char *arg, int unset)
+{
+       int *break_opt = opt->value;
+       int opt1, opt2;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!arg)
+               arg = "";
+       opt1 = parse_rename_score(&arg);
+       if (*arg == 0)
+               opt2 = 0;
+       else if (*arg != '/')
+               return error(_("%s expects <n>/<m> form"), opt->long_name);
+       else {
+               arg++;
+               opt2 = parse_rename_score(&arg);
+       }
+       if (*arg != 0)
+               return error(_("%s expects <n>/<m> form"), opt->long_name);
+       *break_opt = opt1 | (opt2 << 16);
+       return 0;
+}
+
+static int diff_opt_char(const struct option *opt,
+                        const char *arg, int unset)
+{
+       char *value = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (arg[1])
+               return error(_("%s expects a character, got '%s'"),
+                            opt->long_name, arg);
+       *value = arg[0];
+       return 0;
+}
+
+static int diff_opt_color_words(const struct option *opt,
+                               const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       options->use_color = 1;
+       options->word_diff = DIFF_WORDS_COLOR;
+       options->word_regex = arg;
+       return 0;
+}
+
+static int diff_opt_compact_summary(const struct option *opt,
+                                   const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_ARG(arg);
+       if (unset) {
+               options->flags.stat_with_summary = 0;
+       } else {
+               options->flags.stat_with_summary = 1;
+               options->output_format |= DIFF_FORMAT_DIFFSTAT;
+       }
+       return 0;
+}
+
+static int diff_opt_diff_algorithm(const struct option *opt,
+                                  const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+       long value = parse_algorithm_value(arg);
+
+       BUG_ON_OPT_NEG(unset);
+       if (value < 0)
+               return error(_("option diff-algorithm accepts \"myers\", "
+                              "\"minimal\", \"patience\" and \"histogram\""));
+
+       /* clear out previous settings */
+       DIFF_XDL_CLR(options, NEED_MINIMAL);
+       options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
+       options->xdl_opts |= value;
+       return 0;
+}
+
+static int diff_opt_dirstat(const struct option *opt,
+                           const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!strcmp(opt->long_name, "cumulative")) {
+               if (arg)
+                       BUG("how come --cumulative take a value?");
+               arg = "cumulative";
+       } else if (!strcmp(opt->long_name, "dirstat-by-file"))
+               parse_dirstat_opt(options, "files");
+       parse_dirstat_opt(options, arg ? arg : "");
+       return 0;
+}
+
+static int diff_opt_find_copies(const struct option *opt,
+                               const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!arg)
+               arg = "";
+       options->rename_score = parse_rename_score(&arg);
+       if (*arg != 0)
+               return error(_("invalid argument to %s"), opt->long_name);
+
+       if (options->detect_rename == DIFF_DETECT_COPY)
+               options->flags.find_copies_harder = 1;
+       else
+               options->detect_rename = DIFF_DETECT_COPY;
+
+       return 0;
+}
+
+static int diff_opt_find_renames(const struct option *opt,
+                                const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!arg)
+               arg = "";
+       options->rename_score = parse_rename_score(&arg);
+       if (*arg != 0)
+               return error(_("invalid argument to %s"), opt->long_name);
+
+       options->detect_rename = DIFF_DETECT_RENAME;
+       return 0;
+}
+
+static int diff_opt_follow(const struct option *opt,
+                          const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_ARG(arg);
+       if (unset) {
+               options->flags.follow_renames = 0;
+               options->flags.default_follow_renames = 0;
+       } else {
+               options->flags.follow_renames = 1;
+       }
+       return 0;
+}
+
+static int diff_opt_ignore_submodules(const struct option *opt,
+                                     const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!arg)
+               arg = "all";
+       options->flags.override_submodule_config = 1;
+       handle_ignore_submodules_arg(options, arg);
+       return 0;
+}
+
+static enum parse_opt_result diff_opt_output(struct parse_opt_ctx_t *ctx,
+                                            const struct option *opt,
+                                            const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+       char *path;
+
+       BUG_ON_OPT_NEG(unset);
+       path = prefix_filename(ctx->prefix, arg);
+       options->file = xfopen(path, "w");
+       options->close_file = 1;
+       if (options->use_color != GIT_COLOR_ALWAYS)
+               options->use_color = GIT_COLOR_NEVER;
+       free(path);
+       return 0;
+}
+
+static int diff_opt_patience(const struct option *opt,
+                            const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+       int i;
+
+       BUG_ON_OPT_NEG(unset);
+       BUG_ON_OPT_ARG(arg);
+       options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
+       /*
+        * Both --patience and --anchored use PATIENCE_DIFF
+        * internally, so remove any anchors previously
+        * specified.
+        */
+       for (i = 0; i < options->anchors_nr; i++)
+               free(options->anchors[i]);
+       options->anchors_nr = 0;
+       return 0;
+}
+
+static int diff_opt_relative(const struct option *opt,
+                            const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       options->flags.relative_name = 1;
+       if (arg)
+               options->prefix = arg;
+       return 0;
+}
+
+static int diff_opt_submodule(const struct option *opt,
+                             const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (!arg)
+               arg = "log";
+       if (parse_submodule_params(options, arg))
+               return error(_("failed to parse --submodule option parameter: '%s'"),
+                            arg);
+       return 0;
+}
+
+static int diff_opt_textconv(const struct option *opt,
+                            const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_ARG(arg);
+       if (unset) {
+               options->flags.allow_textconv = 0;
+       } else {
+               options->flags.allow_textconv = 1;
+               options->flags.textconv_set_via_cmdline = 1;
+       }
+       return 0;
+}
+
 static int diff_opt_unified(const struct option *opt,
                            const char *arg, int unset)
 {
@@ -4949,6 +5179,44 @@ static int diff_opt_unified(const struct option *opt,
        return 0;
 }
 
+static int diff_opt_word_diff(const struct option *opt,
+                             const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (arg) {
+               if (!strcmp(arg, "plain"))
+                       options->word_diff = DIFF_WORDS_PLAIN;
+               else if (!strcmp(arg, "color")) {
+                       options->use_color = 1;
+                       options->word_diff = DIFF_WORDS_COLOR;
+               }
+               else if (!strcmp(arg, "porcelain"))
+                       options->word_diff = DIFF_WORDS_PORCELAIN;
+               else if (!strcmp(arg, "none"))
+                       options->word_diff = DIFF_WORDS_NONE;
+               else
+                       return error(_("bad --word-diff argument: %s"), arg);
+       } else {
+               if (options->word_diff == DIFF_WORDS_NONE)
+                       options->word_diff = DIFF_WORDS_PLAIN;
+       }
+       return 0;
+}
+
+static int diff_opt_word_diff_regex(const struct option *opt,
+                                   const char *arg, int unset)
+{
+       struct diff_options *options = opt->value;
+
+       BUG_ON_OPT_NEG(unset);
+       if (options->word_diff == DIFF_WORDS_NONE)
+               options->word_diff = DIFF_WORDS_PLAIN;
+       options->word_regex = arg;
+       return 0;
+}
+
 static void prep_parse_options(struct diff_options *options)
 {
        struct option parseopts[] = {
@@ -4956,6 +5224,9 @@ static void prep_parse_options(struct diff_options *options)
                OPT_BITOP('p', "patch", &options->output_format,
                          N_("generate patch"),
                          DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT),
+               OPT_BIT_F('s', "no-patch", &options->output_format,
+                         N_("suppress diff output"),
+                         DIFF_FORMAT_NO_OUTPUT, PARSE_OPT_NONEG),
                OPT_BITOP('u', NULL, &options->output_format,
                          N_("generate patch"),
                          DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT),
@@ -4967,6 +5238,187 @@ static void prep_parse_options(struct diff_options *options)
                OPT_BIT_F(0, "raw", &options->output_format,
                          N_("generate the diff in raw format"),
                          DIFF_FORMAT_RAW, PARSE_OPT_NONEG),
+               OPT_BITOP(0, "patch-with-raw", &options->output_format,
+                         N_("synonym for '-p --raw'"),
+                         DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW,
+                         DIFF_FORMAT_NO_OUTPUT),
+               OPT_BITOP(0, "patch-with-stat", &options->output_format,
+                         N_("synonym for '-p --stat'"),
+                         DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT,
+                         DIFF_FORMAT_NO_OUTPUT),
+               OPT_BIT_F(0, "numstat", &options->output_format,
+                         N_("machine friendly --stat"),
+                         DIFF_FORMAT_NUMSTAT, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "shortstat", &options->output_format,
+                         N_("output only the last line of --stat"),
+                         DIFF_FORMAT_SHORTSTAT, PARSE_OPT_NONEG),
+               OPT_CALLBACK_F('X', "dirstat", options, N_("<param1,param2>..."),
+                              N_("output the distribution of relative amount of changes for each sub-directory"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_dirstat),
+               OPT_CALLBACK_F(0, "cumulative", options, NULL,
+                              N_("synonym for --dirstat=cumulative"),
+                              PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+                              diff_opt_dirstat),
+               OPT_CALLBACK_F(0, "dirstat-by-file", options, N_("<param1,param2>..."),
+                              N_("synonym for --dirstat=files,param1,param2..."),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_dirstat),
+               OPT_BIT_F(0, "check", &options->output_format,
+                         N_("warn if changes introduce conflict markers or whitespace errors"),
+                         DIFF_FORMAT_CHECKDIFF, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "summary", &options->output_format,
+                         N_("condensed summary such as creations, renames and mode changes"),
+                         DIFF_FORMAT_SUMMARY, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "name-only", &options->output_format,
+                         N_("show only names of changed files"),
+                         DIFF_FORMAT_NAME, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "name-status", &options->output_format,
+                         N_("show only names and status of changed files"),
+                         DIFF_FORMAT_NAME_STATUS, PARSE_OPT_NONEG),
+               OPT_CALLBACK_F(0, "stat", options, N_("<width>[,<name-width>[,<count>]]"),
+                              N_("generate diffstat"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG, diff_opt_stat),
+               OPT_CALLBACK_F(0, "stat-width", options, N_("<width>"),
+                              N_("generate diffstat with a given width"),
+                              PARSE_OPT_NONEG, diff_opt_stat),
+               OPT_CALLBACK_F(0, "stat-name-width", options, N_("<width>"),
+                              N_("generate diffstat with a given name width"),
+                              PARSE_OPT_NONEG, diff_opt_stat),
+               OPT_CALLBACK_F(0, "stat-graph-width", options, N_("<width>"),
+                              N_("generate diffstat with a given graph width"),
+                              PARSE_OPT_NONEG, diff_opt_stat),
+               OPT_CALLBACK_F(0, "stat-count", options, N_("<count>"),
+                              N_("generate diffstat with limited lines"),
+                              PARSE_OPT_NONEG, diff_opt_stat),
+               OPT_CALLBACK_F(0, "compact-summary", options, NULL,
+                              N_("generate compact summary in diffstat"),
+                              PARSE_OPT_NOARG, diff_opt_compact_summary),
+               OPT_CALLBACK_F(0, "binary", options, NULL,
+                              N_("output a binary diff that can be applied"),
+                              PARSE_OPT_NONEG | PARSE_OPT_NOARG, diff_opt_binary),
+               OPT_BOOL(0, "full-index", &options->flags.full_index,
+                        N_("show full pre- and post-image object names on the \"index\" lines")),
+               OPT_COLOR_FLAG(0, "color", &options->use_color,
+                              N_("show colored diff")),
+               OPT_CALLBACK_F(0, "output-indicator-new",
+                              &options->output_indicators[OUTPUT_INDICATOR_NEW],
+                              N_("<char>"),
+                              N_("specify the character to indicate a new line instead of '+'"),
+                              PARSE_OPT_NONEG, diff_opt_char),
+               OPT_CALLBACK_F(0, "output-indicator-old",
+                              &options->output_indicators[OUTPUT_INDICATOR_OLD],
+                              N_("<char>"),
+                              N_("specify the character to indicate an old line instead of '-'"),
+                              PARSE_OPT_NONEG, diff_opt_char),
+               OPT_CALLBACK_F(0, "output-indicator-context",
+                              &options->output_indicators[OUTPUT_INDICATOR_CONTEXT],
+                              N_("<char>"),
+                              N_("specify the character to indicate a context instead of ' '"),
+                              PARSE_OPT_NONEG, diff_opt_char),
+
+               OPT_GROUP(N_("Diff rename options")),
+               OPT_CALLBACK_F('B', "break-rewrites", &options->break_opt, N_("<n>[/<m>]"),
+                              N_("break complete rewrite changes into pairs of delete and create"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_break_rewrites),
+               OPT_CALLBACK_F('M', "find-renames", options, N_("<n>"),
+                              N_("detect renames"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_find_renames),
+               OPT_SET_INT_F('D', "irreversible-delete", &options->irreversible_delete,
+                             N_("omit the preimage for deletes"),
+                             1, PARSE_OPT_NONEG),
+               OPT_CALLBACK_F('C', "find-copies", options, N_("<n>"),
+                              N_("detect copies"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_find_copies),
+               OPT_BOOL(0, "find-copies-harder", &options->flags.find_copies_harder,
+                        N_("use unmodified files as source to find copies")),
+               OPT_SET_INT_F(0, "no-renames", &options->detect_rename,
+                             N_("disable rename detection"),
+                             0, PARSE_OPT_NONEG),
+               OPT_BOOL(0, "rename-empty", &options->flags.rename_empty,
+                        N_("use empty blobs as rename source")),
+               OPT_CALLBACK_F(0, "follow", options, NULL,
+                              N_("continue listing the history of a file beyond renames"),
+                              PARSE_OPT_NOARG, diff_opt_follow),
+
+               OPT_GROUP(N_("Diff algorithm options")),
+               OPT_BIT(0, "minimal", &options->xdl_opts,
+                       N_("produce the smallest possible diff"),
+                       XDF_NEED_MINIMAL),
+               OPT_BIT_F('w', "ignore-all-space", &options->xdl_opts,
+                         N_("ignore whitespace when comparing lines"),
+                         XDF_IGNORE_WHITESPACE, PARSE_OPT_NONEG),
+               OPT_BIT_F('b', "ignore-space-change", &options->xdl_opts,
+                         N_("ignore changes in amount of whitespace"),
+                         XDF_IGNORE_WHITESPACE_CHANGE, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "ignore-space-at-eol", &options->xdl_opts,
+                         N_("ignore changes in whitespace at EOL"),
+                         XDF_IGNORE_WHITESPACE_AT_EOL, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "ignore-cr-at-eol", &options->xdl_opts,
+                         N_("ignore carrier-return at the end of line"),
+                         XDF_IGNORE_CR_AT_EOL, PARSE_OPT_NONEG),
+               OPT_BIT_F(0, "ignore-blank-lines", &options->xdl_opts,
+                         N_("ignore changes whose lines are all blank"),
+                         XDF_IGNORE_BLANK_LINES, PARSE_OPT_NONEG),
+               OPT_BIT(0, "indent-heuristic", &options->xdl_opts,
+                       N_("heuristic to shift diff hunk boundaries for easy reading"),
+                       XDF_INDENT_HEURISTIC),
+               OPT_CALLBACK_F(0, "patience", options, NULL,
+                              N_("generate diff using the \"patience diff\" algorithm"),
+                              PARSE_OPT_NONEG | PARSE_OPT_NOARG,
+                              diff_opt_patience),
+               OPT_BITOP(0, "histogram", &options->xdl_opts,
+                         N_("generate diff using the \"histogram diff\" algorithm"),
+                         XDF_HISTOGRAM_DIFF, XDF_DIFF_ALGORITHM_MASK),
+               OPT_CALLBACK_F(0, "diff-algorithm", options, N_("<algorithm>"),
+                              N_("choose a diff algorithm"),
+                              PARSE_OPT_NONEG, diff_opt_diff_algorithm),
+               OPT_CALLBACK_F(0, "anchored", options, N_("<text>"),
+                              N_("generate diff using the \"anchored diff\" algorithm"),
+                              PARSE_OPT_NONEG, diff_opt_anchored),
+               OPT_CALLBACK_F(0, "word-diff", options, N_("<mode>"),
+                              N_("show word diff, using <mode> to delimit changed words"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG, diff_opt_word_diff),
+               OPT_CALLBACK_F(0, "word-diff-regex", options, N_("<regex>"),
+                              N_("use <regex> to decide what a word is"),
+                              PARSE_OPT_NONEG, diff_opt_word_diff_regex),
+               OPT_CALLBACK_F(0, "color-words", options, N_("<regex>"),
+                              N_("equivalent to --word-diff=color --word-diff-regex=<regex>"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG, diff_opt_color_words),
+
+               OPT_GROUP(N_("Diff other options")),
+               OPT_CALLBACK_F(0, "relative", options, N_("<prefix>"),
+                              N_("when run from subdir, exclude changes outside and show relative paths"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_relative),
+               OPT_BOOL('a', "text", &options->flags.text,
+                        N_("treat all files as text")),
+               OPT_BOOL('R', NULL, &options->flags.reverse_diff,
+                        N_("swap two inputs, reverse the diff")),
+               OPT_BOOL(0, "exit-code", &options->flags.exit_with_status,
+                        N_("exit with 1 if there were differences, 0 otherwise")),
+               OPT_BOOL(0, "quiet", &options->flags.quick,
+                        N_("disable all output of the program")),
+               OPT_BOOL(0, "ext-diff", &options->flags.allow_external,
+                        N_("allow an external diff helper to be executed")),
+               OPT_CALLBACK_F(0, "textconv", options, NULL,
+                              N_("run external text conversion filters when comparing binary files"),
+                              PARSE_OPT_NOARG, diff_opt_textconv),
+               OPT_CALLBACK_F(0, "ignore-submodules", options, N_("<when>"),
+                              N_("ignore changes to submodules in the diff generation"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_ignore_submodules),
+               OPT_CALLBACK_F(0, "submodule", options, N_("<format>"),
+                              N_("specify how differences in submodules are shown"),
+                              PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
+                              diff_opt_submodule),
+               { OPTION_CALLBACK, 0, "output", options, N_("<file>"),
+                 N_("Output to a specific file"),
+                 PARSE_OPT_NONEG, NULL, 0, diff_opt_output },
+
                OPT_END()
        };
 
@@ -4994,162 +5446,8 @@ int diff_opt_parse(struct diff_options *options,
        if (ac)
                return ac;
 
-       /* Output format options */
-       if (!strcmp(arg, "--patch-with-raw")) {
-               enable_patch_output(&options->output_format);
-               options->output_format |= DIFF_FORMAT_RAW;
-       } else if (!strcmp(arg, "--numstat"))
-               options->output_format |= DIFF_FORMAT_NUMSTAT;
-       else if (!strcmp(arg, "--shortstat"))
-               options->output_format |= DIFF_FORMAT_SHORTSTAT;
-       else if (skip_prefix(arg, "-X", &arg) ||
-                skip_to_optional_arg(arg, "--dirstat", &arg))
-               return parse_dirstat_opt(options, arg);
-       else if (!strcmp(arg, "--cumulative"))
-               return parse_dirstat_opt(options, "cumulative");
-       else if (skip_to_optional_arg(arg, "--dirstat-by-file", &arg)) {
-               parse_dirstat_opt(options, "files");
-               return parse_dirstat_opt(options, arg);
-       }
-       else if (!strcmp(arg, "--check"))
-               options->output_format |= DIFF_FORMAT_CHECKDIFF;
-       else if (!strcmp(arg, "--summary"))
-               options->output_format |= DIFF_FORMAT_SUMMARY;
-       else if (!strcmp(arg, "--patch-with-stat")) {
-               enable_patch_output(&options->output_format);
-               options->output_format |= DIFF_FORMAT_DIFFSTAT;
-       } else if (!strcmp(arg, "--name-only"))
-               options->output_format |= DIFF_FORMAT_NAME;
-       else if (!strcmp(arg, "--name-status"))
-               options->output_format |= DIFF_FORMAT_NAME_STATUS;
-       else if (!strcmp(arg, "-s") || !strcmp(arg, "--no-patch"))
-               options->output_format |= DIFF_FORMAT_NO_OUTPUT;
-       else if (starts_with(arg, "--stat"))
-               /* --stat, --stat-width, --stat-name-width, or --stat-count */
-               return stat_opt(options, av);
-       else if (!strcmp(arg, "--compact-summary")) {
-                options->flags.stat_with_summary = 1;
-                options->output_format |= DIFF_FORMAT_DIFFSTAT;
-       } else if (!strcmp(arg, "--no-compact-summary"))
-                options->flags.stat_with_summary = 0;
-       else if (skip_prefix(arg, "--output-indicator-new=", &arg))
-               options->output_indicators[OUTPUT_INDICATOR_NEW] = arg[0];
-       else if (skip_prefix(arg, "--output-indicator-old=", &arg))
-               options->output_indicators[OUTPUT_INDICATOR_OLD] = arg[0];
-       else if (skip_prefix(arg, "--output-indicator-context=", &arg))
-               options->output_indicators[OUTPUT_INDICATOR_CONTEXT] = arg[0];
-
-       /* renames options */
-       else if (starts_with(arg, "-B") ||
-                skip_to_optional_arg(arg, "--break-rewrites", NULL)) {
-               if ((options->break_opt = diff_scoreopt_parse(arg)) == -1)
-                       return error("invalid argument to -B: %s", arg+2);
-       }
-       else if (starts_with(arg, "-M") ||
-                skip_to_optional_arg(arg, "--find-renames", NULL)) {
-               if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
-                       return error("invalid argument to -M: %s", arg+2);
-               options->detect_rename = DIFF_DETECT_RENAME;
-       }
-       else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
-               options->irreversible_delete = 1;
-       }
-       else if (starts_with(arg, "-C") ||
-                skip_to_optional_arg(arg, "--find-copies", NULL)) {
-               if (options->detect_rename == DIFF_DETECT_COPY)
-                       options->flags.find_copies_harder = 1;
-               if ((options->rename_score = diff_scoreopt_parse(arg)) == -1)
-                       return error("invalid argument to -C: %s", arg+2);
-               options->detect_rename = DIFF_DETECT_COPY;
-       }
-       else if (!strcmp(arg, "--no-renames"))
-               options->detect_rename = 0;
-       else if (!strcmp(arg, "--rename-empty"))
-               options->flags.rename_empty = 1;
-       else if (!strcmp(arg, "--no-rename-empty"))
-               options->flags.rename_empty = 0;
-       else if (skip_to_optional_arg_default(arg, "--relative", &arg, NULL)) {
-               options->flags.relative_name = 1;
-               if (arg)
-                       options->prefix = arg;
-       }
-
-       /* xdiff options */
-       else if (!strcmp(arg, "--minimal"))
-               DIFF_XDL_SET(options, NEED_MINIMAL);
-       else if (!strcmp(arg, "--no-minimal"))
-               DIFF_XDL_CLR(options, NEED_MINIMAL);
-       else if (!strcmp(arg, "-w") || !strcmp(arg, "--ignore-all-space"))
-               DIFF_XDL_SET(options, IGNORE_WHITESPACE);
-       else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
-               DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
-       else if (!strcmp(arg, "--ignore-space-at-eol"))
-               DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
-       else if (!strcmp(arg, "--ignore-cr-at-eol"))
-               DIFF_XDL_SET(options, IGNORE_CR_AT_EOL);
-       else if (!strcmp(arg, "--ignore-blank-lines"))
-               DIFF_XDL_SET(options, IGNORE_BLANK_LINES);
-       else if (!strcmp(arg, "--indent-heuristic"))
-               DIFF_XDL_SET(options, INDENT_HEURISTIC);
-       else if (!strcmp(arg, "--no-indent-heuristic"))
-               DIFF_XDL_CLR(options, INDENT_HEURISTIC);
-       else if (!strcmp(arg, "--patience")) {
-               int i;
-               options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
-               /*
-                * Both --patience and --anchored use PATIENCE_DIFF
-                * internally, so remove any anchors previously
-                * specified.
-                */
-               for (i = 0; i < options->anchors_nr; i++)
-                       free(options->anchors[i]);
-               options->anchors_nr = 0;
-       } else if (!strcmp(arg, "--histogram"))
-               options->xdl_opts = DIFF_WITH_ALG(options, HISTOGRAM_DIFF);
-       else if ((argcount = parse_long_opt("diff-algorithm", av, &optarg))) {
-               long value = parse_algorithm_value(optarg);
-               if (value < 0)
-                       return error("option diff-algorithm accepts \"myers\", "
-                                    "\"minimal\", \"patience\" and \"histogram\"");
-               /* clear out previous settings */
-               DIFF_XDL_CLR(options, NEED_MINIMAL);
-               options->xdl_opts &= ~XDF_DIFF_ALGORITHM_MASK;
-               options->xdl_opts |= value;
-               return argcount;
-       } else if (skip_prefix(arg, "--anchored=", &arg)) {
-               options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
-               ALLOC_GROW(options->anchors, options->anchors_nr + 1,
-                          options->anchors_alloc);
-               options->anchors[options->anchors_nr++] = xstrdup(arg);
-       }
-
        /* flags options */
-       else if (!strcmp(arg, "--binary")) {
-               enable_patch_output(&options->output_format);
-               options->flags.binary = 1;
-       }
-       else if (!strcmp(arg, "--full-index"))
-               options->flags.full_index = 1;
-       else if (!strcmp(arg, "-a") || !strcmp(arg, "--text"))
-               options->flags.text = 1;
-       else if (!strcmp(arg, "-R"))
-               options->flags.reverse_diff = 1;
-       else if (!strcmp(arg, "--find-copies-harder"))
-               options->flags.find_copies_harder = 1;
-       else if (!strcmp(arg, "--follow"))
-               options->flags.follow_renames = 1;
-       else if (!strcmp(arg, "--no-follow")) {
-               options->flags.follow_renames = 0;
-               options->flags.default_follow_renames = 0;
-       } else if (skip_to_optional_arg_default(arg, "--color", &arg, "always")) {
-               int value = git_config_colorbool(NULL, arg);
-               if (value < 0)
-                       return error("option `color' expects \"always\", \"auto\", or \"never\"");
-               options->use_color = value;
-       }
-       else if (!strcmp(arg, "--no-color"))
-               options->use_color = 0;
-       else if (!strcmp(arg, "--color-moved")) {
+       if (!strcmp(arg, "--color-moved")) {
                if (diff_color_moved_default)
                        options->color_moved = diff_color_moved_default;
                if (options->color_moved == COLOR_MOVED_NO)
@@ -5168,53 +5466,7 @@ int diff_opt_parse(struct diff_options *options,
                if (cm & COLOR_MOVED_WS_ERROR)
                        return -1;
                options->color_moved_ws_handling = cm;
-       } else if (skip_to_optional_arg_default(arg, "--color-words", &options->word_regex, NULL)) {
-               options->use_color = 1;
-               options->word_diff = DIFF_WORDS_COLOR;
-       }
-       else if (!strcmp(arg, "--word-diff")) {
-               if (options->word_diff == DIFF_WORDS_NONE)
-                       options->word_diff = DIFF_WORDS_PLAIN;
-       }
-       else if (skip_prefix(arg, "--word-diff=", &arg)) {
-               if (!strcmp(arg, "plain"))
-                       options->word_diff = DIFF_WORDS_PLAIN;
-               else if (!strcmp(arg, "color")) {
-                       options->use_color = 1;
-                       options->word_diff = DIFF_WORDS_COLOR;
-               }
-               else if (!strcmp(arg, "porcelain"))
-                       options->word_diff = DIFF_WORDS_PORCELAIN;
-               else if (!strcmp(arg, "none"))
-                       options->word_diff = DIFF_WORDS_NONE;
-               else
-                       die("bad --word-diff argument: %s", arg);
-       }
-       else if ((argcount = parse_long_opt("word-diff-regex", av, &optarg))) {
-               if (options->word_diff == DIFF_WORDS_NONE)
-                       options->word_diff = DIFF_WORDS_PLAIN;
-               options->word_regex = optarg;
-               return argcount;
-       }
-       else if (!strcmp(arg, "--exit-code"))
-               options->flags.exit_with_status = 1;
-       else if (!strcmp(arg, "--quiet"))
-               options->flags.quick = 1;
-       else if (!strcmp(arg, "--ext-diff"))
-               options->flags.allow_external = 1;
-       else if (!strcmp(arg, "--no-ext-diff"))
-               options->flags.allow_external = 0;
-       else if (!strcmp(arg, "--textconv")) {
-               options->flags.allow_textconv = 1;
-               options->flags.textconv_set_via_cmdline = 1;
-       } else if (!strcmp(arg, "--no-textconv"))
-               options->flags.allow_textconv = 0;
-       else if (skip_to_optional_arg_default(arg, "--ignore-submodules", &arg, "all")) {
-               options->flags.override_submodule_config = 1;
-               handle_ignore_submodules_arg(options, arg);
-       } else if (skip_to_optional_arg_default(arg, "--submodule", &arg, "log"))
-               return parse_submodule_opt(options, arg);
-       else if (skip_prefix(arg, "--ws-error-highlight=", &arg))
+       } else if (skip_prefix(arg, "--ws-error-highlight=", &arg))
                return parse_ws_error_highlight_opt(options, arg);
        else if (!strcmp(arg, "--ita-invisible-in-index"))
                options->ita_invisible_in_index = 1;
@@ -5283,15 +5535,7 @@ int diff_opt_parse(struct diff_options *options,
        else if (opt_arg(arg, '\0', "inter-hunk-context",
                         &options->interhunkcontext))
                ;
-       else if ((argcount = parse_long_opt("output", av, &optarg))) {
-               char *path = prefix_filename(prefix, optarg);
-               options->file = xfopen(path, "w");
-               options->close_file = 1;
-               if (options->use_color != GIT_COLOR_ALWAYS)
-                       options->use_color = GIT_COLOR_NEVER;
-               free(path);
-               return argcount;
-       } else
+       else
                return 0;
        return 1;
 }
@@ -5332,47 +5576,6 @@ int parse_rename_score(const char **cp_p)
        return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale));
 }
 
-static int diff_scoreopt_parse(const char *opt)
-{
-       int opt1, opt2, cmd;
-
-       if (*opt++ != '-')
-               return -1;
-       cmd = *opt++;
-       if (cmd == '-') {
-               /* convert the long-form arguments into short-form versions */
-               if (skip_prefix(opt, "break-rewrites", &opt)) {
-                       if (*opt == 0 || *opt++ == '=')
-                               cmd = 'B';
-               } else if (skip_prefix(opt, "find-copies", &opt)) {
-                       if (*opt == 0 || *opt++ == '=')
-                               cmd = 'C';
-               } else if (skip_prefix(opt, "find-renames", &opt)) {
-                       if (*opt == 0 || *opt++ == '=')
-                               cmd = 'M';
-               }
-       }
-       if (cmd != 'M' && cmd != 'C' && cmd != 'B')
-               return -1; /* that is not a -M, -C, or -B option */
-
-       opt1 = parse_rename_score(&opt);
-       if (cmd != 'B')
-               opt2 = 0;
-       else {
-               if (*opt == 0)
-                       opt2 = 0;
-               else if (*opt != '/')
-                       return -1; /* we expect -B80/99 or -B80 */
-               else {
-                       opt++;
-                       opt2 = parse_rename_score(&opt);
-               }
-       }
-       if (*opt != 0)
-               return -1;
-       return opt1 | (opt2 << 16);
-}
-
 struct diff_queue_struct diff_queued_diff;
 
 void diff_q(struct diff_queue_struct *queue, struct diff_filepair *dp)
@@ -6271,7 +6474,7 @@ static int diffnamecmp(const void *a_, const void *b_)
        return strcmp(name_a, name_b);
 }
 
-void diffcore_fix_diff_index(struct diff_options *options)
+void diffcore_fix_diff_index(void)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        QSORT(q->queue, q->nr, diffnamecmp);
diff --git a/diff.h b/diff.h
index 3199ba31f8d697d0a73f64cde12433d8f1244181..c9db9825bb782fda45f463c3f51600fb3756b7c1 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -370,7 +370,7 @@ int git_config_rename(const char *var, const char *value);
 #define DIFF_PICKAXE_IGNORE_CASE       32
 
 void diffcore_std(struct diff_options *);
-void diffcore_fix_diff_index(struct diff_options *);
+void diffcore_fix_diff_index(void);
 
 #define COMMON_DIFF_OPTIONS_HELP \
 "\ncommon diff options:\n" \
@@ -438,7 +438,7 @@ int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
 
 int diff_result_code(struct diff_options *, int);
 
-void diff_no_index(struct repository *, struct rev_info *, int, const char **);
+void diff_no_index(struct rev_info *, int, const char **);
 
 int index_differs_from(struct repository *r, const char *def,
                       const struct diff_flags *flags,
index 812be15d7e568522973227bb939343d94c008ceb..e69993b2eb56885253af21b6de33fd487725e313 100644 (file)
@@ -191,8 +191,10 @@ static void send_request(struct fetch_pack_args *args,
        if (args->stateless_rpc) {
                send_sideband(fd, -1, buf->buf, buf->len, LARGE_PACKET_MAX);
                packet_flush(fd);
-       } else
-               write_or_die(fd, buf->buf, buf->len);
+       } else {
+               if (write_in_full(fd, buf->buf, buf->len) < 0)
+                       die_errno(_("unable to write to remote"));
+       }
 }
 
 static void insert_one_alternate_object(struct fetch_negotiator *negotiator,
@@ -1163,7 +1165,8 @@ static int send_fetch_request(struct fetch_negotiator *negotiator, int fd_out,
 
        /* Send request */
        packet_buf_flush(&req_buf);
-       write_or_die(fd_out, req_buf.buf, req_buf.len);
+       if (write_in_full(fd_out, req_buf.buf, req_buf.len) < 0)
+               die_errno(_("unable to write request to remote"));
 
        strbuf_release(&req_buf);
        return ret;
diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
deleted file mode 100755 (executable)
index 5c2c4e5..0000000
+++ /dev/null
@@ -1,770 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano.
-#
-
-SUBDIRECTORY_OK=Yes
-OPTIONS_KEEPDASHDASH=
-OPTIONS_STUCKLONG=t
-OPTIONS_SPEC="\
-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]
-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]
-git rebase --continue | --abort | --skip | --edit-todo
---
- Available options are
-v,verbose!         display a diffstat of what changed upstream
-q,quiet!           be quiet. implies --no-stat
-autostash          automatically stash/stash pop before and after
-fork-point         use 'merge-base --fork-point' to refine upstream
-onto=!             rebase onto given branch instead of upstream
-r,rebase-merges?   try to rebase merges instead of skipping them
-p,preserve-merges! try to recreate merges instead of ignoring them
-s,strategy=!       use the given merge strategy
-X,strategy-option=! pass the argument through to the merge strategy
-no-ff!             cherry-pick all commits, even if unchanged
-f,force-rebase!    cherry-pick all commits, even if unchanged
-m,merge!           use merging strategies to rebase
-i,interactive!     let the user edit the list of commits to rebase
-x,exec=!           add exec lines after each commit of the editable list
-k,keep-empty      preserve empty commits during rebase
-allow-empty-message allow rebasing commits with empty messages
-stat!              display a diffstat of what changed upstream
-n,no-stat!         do not show diffstat of what changed upstream
-verify             allow pre-rebase hook to run
-rerere-autoupdate  allow rerere to update index with resolved conflicts
-root!              rebase all reachable commits up to the root(s)
-autosquash         move commits that begin with squash!/fixup! under -i
-signoff            add a Signed-off-by: line to each commit
-committer-date-is-author-date! passed to 'git am'
-ignore-date!       passed to 'git am'
-whitespace=!       passed to 'git apply'
-ignore-whitespace! passed to 'git apply'
-C=!                passed to 'git apply'
-S,gpg-sign?        GPG-sign commits
- Actions:
-continue!          continue
-abort!             abort and check out the original branch
-skip!              skip current patch and continue
-edit-todo!         edit the todo list during an interactive rebase
-quit!              abort but keep HEAD where it is
-show-current-patch! show the patch file being applied or merged
-reschedule-failed-exec automatically reschedule failed exec commands
-"
-. git-sh-setup
-set_reflog_action rebase
-require_work_tree_exists
-cd_to_toplevel
-
-LF='
-'
-ok_to_skip_pre_rebase=
-
-squash_onto=
-unset onto
-unset restrict_revision
-cmd=
-strategy=
-strategy_opts=
-do_merge=
-merge_dir="$GIT_DIR"/rebase-merge
-apply_dir="$GIT_DIR"/rebase-apply
-verbose=
-diffstat=
-test "$(git config --bool rebase.stat)" = true && diffstat=t
-autostash="$(git config --bool rebase.autostash || echo false)"
-fork_point=auto
-git_am_opt=
-git_format_patch_opt=
-rebase_root=
-force_rebase=
-allow_rerere_autoupdate=
-# Non-empty if a rebase was in progress when 'git rebase' was invoked
-in_progress=
-# One of {am, merge, interactive}
-type=
-# One of {"$GIT_DIR"/rebase-apply, "$GIT_DIR"/rebase-merge}
-state_dir=
-# One of {'', continue, skip, abort}, as parsed from command line
-action=
-rebase_merges=
-rebase_cousins=
-preserve_merges=
-autosquash=
-keep_empty=
-allow_empty_message=--allow-empty-message
-signoff=
-reschedule_failed_exec=
-test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
-case "$(git config --bool commit.gpgsign)" in
-true)  gpg_sign_opt=-S ;;
-*)     gpg_sign_opt= ;;
-esac
-test "$(git config --bool rebase.reschedulefailedexec)" = "true" &&
-reschedule_failed_exec=--reschedule-failed-exec
-. git-rebase--common
-
-read_basic_state () {
-       test -f "$state_dir/head-name" &&
-       test -f "$state_dir/onto" &&
-       head_name=$(cat "$state_dir"/head-name) &&
-       onto=$(cat "$state_dir"/onto) &&
-       # We always write to orig-head, but interactive rebase used to write to
-       # head. Fall back to reading from head to cover for the case that the
-       # user upgraded git with an ongoing interactive rebase.
-       if test -f "$state_dir"/orig-head
-       then
-               orig_head=$(cat "$state_dir"/orig-head)
-       else
-               orig_head=$(cat "$state_dir"/head)
-       fi &&
-       test -f "$state_dir"/quiet && GIT_QUIET=t
-       test -f "$state_dir"/verbose && verbose=t
-       test -f "$state_dir"/strategy && strategy="$(cat "$state_dir"/strategy)"
-       test -f "$state_dir"/strategy_opts &&
-               strategy_opts="$(cat "$state_dir"/strategy_opts)"
-       test -f "$state_dir"/allow_rerere_autoupdate &&
-               allow_rerere_autoupdate="$(cat "$state_dir"/allow_rerere_autoupdate)"
-       test -f "$state_dir"/gpg_sign_opt &&
-               gpg_sign_opt="$(cat "$state_dir"/gpg_sign_opt)"
-       test -f "$state_dir"/signoff && {
-               signoff="$(cat "$state_dir"/signoff)"
-               force_rebase=t
-       }
-       test -f "$state_dir"/reschedule-failed-exec &&
-               reschedule_failed_exec=t
-}
-
-finish_rebase () {
-       rm -f "$(git rev-parse --git-path REBASE_HEAD)"
-       apply_autostash &&
-       { git gc --auto || true; } &&
-       rm -rf "$state_dir"
-}
-
-run_interactive () {
-       GIT_CHERRY_PICK_HELP="$resolvemsg"
-       export GIT_CHERRY_PICK_HELP
-
-       test -n "$keep_empty" && keep_empty="--keep-empty"
-       test -n "$rebase_merges" && rebase_merges="--rebase-merges"
-       test -n "$rebase_cousins" && rebase_cousins="--rebase-cousins"
-       test -n "$autosquash" && autosquash="--autosquash"
-       test -n "$verbose" && verbose="--verbose"
-       test -n "$force_rebase" && force_rebase="--no-ff"
-       test -n "$restrict_revision" && \
-               restrict_revision="--restrict-revision=^$restrict_revision"
-       test -n "$upstream" && upstream="--upstream=$upstream"
-       test -n "$onto" && onto="--onto=$onto"
-       test -n "$squash_onto" && squash_onto="--squash-onto=$squash_onto"
-       test -n "$onto_name" && onto_name="--onto-name=$onto_name"
-       test -n "$head_name" && head_name="--head-name=$head_name"
-       test -n "$strategy" && strategy="--strategy=$strategy"
-       test -n "$strategy_opts" && strategy_opts="--strategy-opts=$strategy_opts"
-       test -n "$switch_to" && switch_to="--switch-to=$switch_to"
-       test -n "$cmd" && cmd="--cmd=$cmd"
-       test -n "$action" && action="--$action"
-
-       exec git rebase--interactive "$action" "$keep_empty" "$rebase_merges" "$rebase_cousins" \
-               "$upstream" "$onto" "$squash_onto" "$restrict_revision" \
-               "$allow_empty_message" "$autosquash" "$verbose" \
-               "$force_rebase" "$onto_name" "$head_name" "$strategy" \
-               "$strategy_opts" "$cmd" "$switch_to" \
-               "$allow_rerere_autoupdate" "$gpg_sign_opt" "$signoff" \
-               "$reschedule_failed_exec"
-}
-
-run_specific_rebase () {
-       if [ "$interactive_rebase" = implied ]; then
-               GIT_SEQUENCE_EDITOR=:
-               export GIT_SEQUENCE_EDITOR
-               autosquash=
-       fi
-
-       if test -n "$interactive_rebase" -a -z "$preserve_merges"
-       then
-               run_interactive
-       else
-               . git-rebase--$type
-
-               if test -z "$preserve_merges"
-               then
-                       git_rebase__$type
-               else
-                       git_rebase__preserve_merges
-               fi
-       fi
-
-       ret=$?
-       if test $ret -eq 0
-       then
-               finish_rebase
-       elif test $ret -eq 2 # special exit status for rebase -p
-       then
-               apply_autostash &&
-               rm -rf "$state_dir" &&
-               die "Nothing to do"
-       fi
-       exit $ret
-}
-
-run_pre_rebase_hook () {
-       if test -z "$ok_to_skip_pre_rebase" &&
-          test -x "$(git rev-parse --git-path hooks/pre-rebase)"
-       then
-               "$(git rev-parse --git-path hooks/pre-rebase)" ${1+"$@"} ||
-               die "$(gettext "The pre-rebase hook refused to rebase.")"
-       fi
-}
-
-test -f "$apply_dir"/applying &&
-       die "$(gettext "It looks like 'git am' is in progress. Cannot rebase.")"
-
-if test -d "$apply_dir"
-then
-       type=am
-       state_dir="$apply_dir"
-elif test -d "$merge_dir"
-then
-       type=interactive
-       if test -d "$merge_dir"/rewritten
-       then
-               type=preserve-merges
-               interactive_rebase=explicit
-               preserve_merges=t
-       elif test -f "$merge_dir"/interactive
-       then
-               interactive_rebase=explicit
-       fi
-       state_dir="$merge_dir"
-fi
-test -n "$type" && in_progress=t
-
-total_argc=$#
-while test $# != 0
-do
-       case "$1" in
-       --no-verify)
-               ok_to_skip_pre_rebase=yes
-               ;;
-       --verify)
-               ok_to_skip_pre_rebase=
-               ;;
-       --continue|--skip|--abort|--quit|--edit-todo|--show-current-patch)
-               test $total_argc -eq 2 || usage
-               action=${1##--}
-               ;;
-       --onto=*)
-               onto="${1#--onto=}"
-               ;;
-       --exec=*)
-               cmd="${cmd}exec ${1#--exec=}${LF}"
-               test -z "$interactive_rebase" && interactive_rebase=implied
-               ;;
-       --interactive)
-               interactive_rebase=explicit
-               ;;
-       --keep-empty)
-               keep_empty=yes
-               ;;
-       --allow-empty-message)
-               allow_empty_message=--allow-empty-message
-               ;;
-       --no-keep-empty)
-               keep_empty=
-               ;;
-       --rebase-merges)
-               rebase_merges=t
-               test -z "$interactive_rebase" && interactive_rebase=implied
-               ;;
-       --rebase-merges=*)
-               rebase_merges=t
-               case "${1#*=}" in
-               rebase-cousins) rebase_cousins=t;;
-               no-rebase-cousins) rebase_cousins=;;
-               *) die "Unknown mode: $1";;
-               esac
-               test -z "$interactive_rebase" && interactive_rebase=implied
-               ;;
-       --preserve-merges)
-               preserve_merges=t
-               test -z "$interactive_rebase" && interactive_rebase=implied
-               ;;
-       --autosquash)
-               autosquash=t
-               ;;
-       --no-autosquash)
-               autosquash=
-               ;;
-       --fork-point)
-               fork_point=t
-               ;;
-       --no-fork-point)
-               fork_point=
-               ;;
-       --merge)
-               do_merge=t
-               ;;
-       --strategy-option=*)
-               strategy_opts="$strategy_opts $(git rev-parse --sq-quote "--${1#--strategy-option=}" | sed -e s/^.//)"
-               do_merge=t
-               test -z "$strategy" && strategy=recursive
-               ;;
-       --strategy=*)
-               strategy="${1#--strategy=}"
-               do_merge=t
-               ;;
-       --no-stat)
-               diffstat=
-               ;;
-       --stat)
-               diffstat=t
-               ;;
-       --autostash)
-               autostash=true
-               ;;
-       --no-autostash)
-               autostash=false
-               ;;
-       --verbose)
-               verbose=t
-               diffstat=t
-               GIT_QUIET=
-               ;;
-       --quiet)
-               GIT_QUIET=t
-               git_am_opt="$git_am_opt -q"
-               verbose=
-               diffstat=
-               ;;
-       --whitespace=*)
-               git_am_opt="$git_am_opt --whitespace=${1#--whitespace=}"
-               case "${1#--whitespace=}" in
-               fix|strip)
-                       force_rebase=t
-                       ;;
-               warn|nowarn|error|error-all)
-                       ;; # okay, known whitespace option
-               *)
-                       die "fatal: Invalid whitespace option: '${1#*=}'"
-                       ;;
-               esac
-               ;;
-       --ignore-whitespace)
-               git_am_opt="$git_am_opt $1"
-               ;;
-       --signoff)
-               signoff=--signoff
-               ;;
-       --no-signoff)
-               signoff=
-               ;;
-       --committer-date-is-author-date|--ignore-date)
-               git_am_opt="$git_am_opt $1"
-               force_rebase=t
-               ;;
-       -C*[!0-9]*)
-               die "fatal: switch \`C' expects a numerical value"
-               ;;
-       -C*)
-               git_am_opt="$git_am_opt $1"
-               ;;
-       --root)
-               rebase_root=t
-               ;;
-       --force-rebase|--no-ff)
-               force_rebase=t
-               ;;
-       --rerere-autoupdate|--no-rerere-autoupdate)
-               allow_rerere_autoupdate="$1"
-               ;;
-       --gpg-sign)
-               gpg_sign_opt=-S
-               ;;
-       --gpg-sign=*)
-               gpg_sign_opt="-S${1#--gpg-sign=}"
-               ;;
-       --reschedule-failed-exec)
-               reschedule_failed_exec=--reschedule-failed-exec
-               ;;
-       --no-reschedule-failed-exec)
-               reschedule_failed_exec=
-               ;;
-       --)
-               shift
-               break
-               ;;
-       *)
-               usage
-               ;;
-       esac
-       shift
-done
-test $# -gt 2 && usage
-
-if test -n "$action"
-then
-       test -z "$in_progress" && die "$(gettext "No rebase in progress?")"
-       # Only interactive rebase uses detailed reflog messages
-       if test -n "$interactive_rebase" && test "$GIT_REFLOG_ACTION" = rebase
-       then
-               GIT_REFLOG_ACTION="rebase -i ($action)"
-               export GIT_REFLOG_ACTION
-       fi
-fi
-
-if test "$action" = "edit-todo" && test -z "$interactive_rebase"
-then
-       die "$(gettext "The --edit-todo action can only be used during interactive rebase.")"
-fi
-
-case "$action" in
-continue)
-       # Sanity check
-       git rev-parse --verify HEAD >/dev/null ||
-               die "$(gettext "Cannot read HEAD")"
-       git update-index --ignore-submodules --refresh &&
-       git diff-files --quiet --ignore-submodules || {
-               echo "$(gettext "You must edit all merge conflicts and then
-mark them as resolved using git add")"
-               exit 1
-       }
-       read_basic_state
-       run_specific_rebase
-       ;;
-skip)
-       output git reset --hard HEAD || exit $?
-       read_basic_state
-       run_specific_rebase
-       ;;
-abort)
-       git rerere clear
-       read_basic_state
-       case "$head_name" in
-       refs/*)
-               git symbolic-ref -m "rebase: aborting" HEAD $head_name ||
-               die "$(eval_gettext "Could not move back to \$head_name")"
-               ;;
-       esac
-       output git reset --hard $orig_head
-       finish_rebase
-       exit
-       ;;
-quit)
-       exec rm -rf "$state_dir"
-       ;;
-edit-todo)
-       run_specific_rebase
-       ;;
-show-current-patch)
-       run_specific_rebase
-       die "BUG: run_specific_rebase is not supposed to return here"
-       ;;
-esac
-
-# Make sure no rebase is in progress
-if test -n "$in_progress"
-then
-       state_dir_base=${state_dir##*/}
-       cmd_live_rebase="git rebase (--continue | --abort | --skip)"
-       cmd_clear_stale_rebase="rm -fr \"$state_dir\""
-       die "
-$(eval_gettext 'It seems that there is already a $state_dir_base directory, and
-I wonder if you are in the middle of another rebase.  If that is the
-case, please try
-       $cmd_live_rebase
-If that is not the case, please
-       $cmd_clear_stale_rebase
-and run me again.  I am stopping in case you still have something
-valuable there.')"
-fi
-
-if test -n "$rebase_root" && test -z "$onto"
-then
-       test -z "$interactive_rebase" && interactive_rebase=implied
-fi
-
-if test -n "$keep_empty"
-then
-       test -z "$interactive_rebase" && interactive_rebase=implied
-fi
-
-actually_interactive=
-if test -n "$interactive_rebase"
-then
-       if test -z "$preserve_merges"
-       then
-               type=interactive
-       else
-               type=preserve-merges
-       fi
-       actually_interactive=t
-       state_dir="$merge_dir"
-elif test -n "$do_merge"
-then
-       interactive_rebase=implied
-       type=interactive
-       state_dir="$merge_dir"
-else
-       type=am
-       state_dir="$apply_dir"
-fi
-
-if test -t 2 && test -z "$GIT_QUIET"
-then
-       git_format_patch_opt="$git_format_patch_opt --progress"
-fi
-
-incompatible_opts=$(echo " $git_am_opt " | \
-                   sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
-if test -n "$incompatible_opts"
-then
-       if test -n "$actually_interactive" || test "$do_merge"
-       then
-               die "$(gettext "fatal: cannot combine am options with either interactive or merge options")"
-       fi
-fi
-
-if test -n "$signoff"
-then
-       test -n "$preserve_merges" &&
-               die "$(gettext "fatal: cannot combine '--signoff' with '--preserve-merges'")"
-       git_am_opt="$git_am_opt $signoff"
-       force_rebase=t
-fi
-
-if test -n "$preserve_merges"
-then
-       # Note: incompatibility with --signoff handled in signoff block above
-       # Note: incompatibility with --interactive is just a strong warning;
-       #       git-rebase.txt caveats with "unless you know what you are doing"
-       test -n "$rebase_merges" &&
-               die "$(gettext "fatal: cannot combine '--preserve-merges' with '--rebase-merges'")"
-
-       test -n "$reschedule_failed_exec" &&
-               die "$(gettext "error: cannot combine '--preserve-merges' with '--reschedule-failed-exec'")"
-fi
-
-if test -n "$rebase_merges"
-then
-       test -n "$strategy_opts" &&
-               die "$(gettext "fatal: cannot combine '--rebase-merges' with '--strategy-option'")"
-       test -n "$strategy" &&
-               die "$(gettext "fatal: cannot combine '--rebase-merges' with '--strategy'")"
-fi
-
-if test -z "$rebase_root"
-then
-       case "$#" in
-       0)
-               if ! upstream_name=$(git rev-parse --symbolic-full-name \
-                       --verify -q @{upstream} 2>/dev/null)
-               then
-                       . git-parse-remote
-                       error_on_missing_default_upstream "rebase" "rebase" \
-                               "against" "git rebase $(gettext '<branch>')"
-               fi
-
-               test "$fork_point" = auto && fork_point=t
-               ;;
-       *)      upstream_name="$1"
-               if test "$upstream_name" = "-"
-               then
-                       upstream_name="@{-1}"
-               fi
-               shift
-               ;;
-       esac
-       upstream=$(peel_committish "${upstream_name}") ||
-       die "$(eval_gettext "invalid upstream '\$upstream_name'")"
-       upstream_arg="$upstream_name"
-else
-       if test -z "$onto"
-       then
-               empty_tree=$(git hash-object -t tree /dev/null)
-               onto=$(git commit-tree $empty_tree </dev/null)
-               squash_onto="$onto"
-       fi
-       unset upstream_name
-       unset upstream
-       test $# -gt 1 && usage
-       upstream_arg=--root
-fi
-
-# Make sure the branch to rebase onto is valid.
-onto_name=${onto-"$upstream_name"}
-case "$onto_name" in
-*...*)
-       if      left=${onto_name%...*} right=${onto_name#*...} &&
-               onto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})
-       then
-               case "$onto" in
-               ?*"$LF"?*)
-                       die "$(eval_gettext "\$onto_name: there are more than one merge bases")"
-                       ;;
-               '')
-                       die "$(eval_gettext "\$onto_name: there is no merge base")"
-                       ;;
-               esac
-       else
-               die "$(eval_gettext "\$onto_name: there is no merge base")"
-       fi
-       ;;
-*)
-       onto=$(peel_committish "$onto_name") ||
-       die "$(eval_gettext "Does not point to a valid commit: \$onto_name")"
-       ;;
-esac
-
-# If the branch to rebase is given, that is the branch we will rebase
-# $branch_name -- branch/commit being rebased, or HEAD (already detached)
-# $orig_head -- commit object name of tip of the branch before rebasing
-# $head_name -- refs/heads/<that-branch> or "detached HEAD"
-switch_to=
-case "$#" in
-1)
-       # Is it "rebase other $branchname" or "rebase other $commit"?
-       branch_name="$1"
-       switch_to="$1"
-
-       # Is it a local branch?
-       if git show-ref --verify --quiet -- "refs/heads/$branch_name" &&
-          orig_head=$(git rev-parse -q --verify "refs/heads/$branch_name")
-       then
-               head_name="refs/heads/$branch_name"
-       # If not is it a valid ref (branch or commit)?
-       elif orig_head=$(git rev-parse -q --verify "$branch_name")
-       then
-               head_name="detached HEAD"
-
-       else
-               die "$(eval_gettext "fatal: no such branch/commit '\$branch_name'")"
-       fi
-       ;;
-0)
-       # Do not need to switch branches, we are already on it.
-       if branch_name=$(git symbolic-ref -q HEAD)
-       then
-               head_name=$branch_name
-               branch_name=$(expr "z$branch_name" : 'zrefs/heads/\(.*\)')
-       else
-               head_name="detached HEAD"
-               branch_name=HEAD
-       fi
-       orig_head=$(git rev-parse --verify HEAD) || exit
-       ;;
-*)
-       die "BUG: unexpected number of arguments left to parse"
-       ;;
-esac
-
-if test "$fork_point" = t
-then
-       new_upstream=$(git merge-base --fork-point "$upstream_name" \
-                       "${switch_to:-HEAD}")
-       if test -n "$new_upstream"
-       then
-               restrict_revision=$new_upstream
-       fi
-fi
-
-if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
-then
-       stash_sha1=$(git stash create "autostash") ||
-       die "$(gettext 'Cannot autostash')"
-
-       mkdir -p "$state_dir" &&
-       echo $stash_sha1 >"$state_dir/autostash" &&
-       stash_abbrev=$(git rev-parse --short $stash_sha1) &&
-       echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
-       git reset --hard
-fi
-
-require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
-
-# Now we are rebasing commits $upstream..$orig_head (or with --root,
-# everything leading up to $orig_head) on top of $onto
-
-# Check if we are already based on $onto with linear history,
-# but this should be done only when upstream and onto are the same
-# and if this is not an interactive rebase.
-mb=$(git merge-base "$onto" "$orig_head")
-if test -z "$actually_interactive" && test "$upstream" = "$onto" &&
-       test "$mb" = "$onto" && test -z "$restrict_revision" &&
-       # linear history?
-       ! (git rev-list --parents "$onto".."$orig_head" | sane_grep " .* ") > /dev/null
-then
-       if test -z "$force_rebase"
-       then
-               # Lazily switch to the target branch if needed...
-               test -z "$switch_to" ||
-               GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" \
-                       git checkout -q "$switch_to" --
-               if test "$branch_name" = "HEAD" &&
-                        ! git symbolic-ref -q HEAD
-               then
-                       say "$(eval_gettext "HEAD is up to date.")"
-               else
-                       say "$(eval_gettext "Current branch \$branch_name is up to date.")"
-               fi
-               finish_rebase
-               exit 0
-       else
-               if test "$branch_name" = "HEAD" &&
-                        ! git symbolic-ref -q HEAD
-               then
-                       say "$(eval_gettext "HEAD is up to date, rebase forced.")"
-               else
-                       say "$(eval_gettext "Current branch \$branch_name is up to date, rebase forced.")"
-               fi
-       fi
-fi
-
-# If a hook exists, give it a chance to interrupt
-run_pre_rebase_hook "$upstream_arg" "$@"
-
-if test -n "$diffstat"
-then
-       if test -n "$verbose"
-       then
-               if test -z "$mb"
-               then
-                       echo "$(eval_gettext "Changes to \$onto:")"
-               else
-                       echo "$(eval_gettext "Changes from \$mb to \$onto:")"
-               fi
-       fi
-       mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
-       # We want color (if set), but no pager
-       GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
-fi
-
-if test -z "$actually_interactive" && test "$mb" = "$orig_head"
-then
-       say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
-       GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
-               git checkout -q "$onto^0" || die "could not detach HEAD"
-       # If the $onto is a proper descendant of the tip of the branch, then
-       # we just fast-forwarded.
-       git update-ref ORIG_HEAD $orig_head
-       move_to_original_branch
-       finish_rebase
-       exit 0
-fi
-
-test -n "$interactive_rebase" && run_specific_rebase
-
-# Detach HEAD and reset the tree
-say "$(gettext "First, rewinding head to replay your work on top of it...")"
-
-GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
-       git checkout -q "$onto^0" || die "could not detach HEAD"
-git update-ref ORIG_HEAD $orig_head
-
-if test -n "$rebase_root"
-then
-       revisions="$onto..$orig_head"
-else
-       revisions="${restrict_revision-$upstream}..$orig_head"
-fi
-
-run_specific_rebase
index 8eb63b5a2f8d07038f6c8ef645a483cd77ffd99f..8200d58cdc62b628f77923305ecb79ff260155ea 100755 (executable)
@@ -465,6 +465,8 @@ sub read_config {
 my(%suppress_cc);
 if (@suppress_cc) {
        foreach my $entry (@suppress_cc) {
+               # Please update $__git_send_email_suppresscc_options
+               # in git-completion.bash when you add new options.
                die sprintf(__("Unknown --suppress-cc field: '%s'\n"), $entry)
                        unless $entry =~ /^(?:all|cccmd|cc|author|self|sob|body|bodycc|misc-by)$/;
                $suppress_cc{$entry} = 1;
@@ -494,6 +496,8 @@ sub read_config {
 if ($confirm_unconfigured) {
        $confirm = scalar %suppress_cc ? 'compose' : 'auto';
 };
+# Please update $__git_send_email_confirm_options in
+# git-completion.bash when you add new options.
 die sprintf(__("Unknown --confirm setting: '%s'\n"), $confirm)
        unless $confirm =~ /^(?:auto|cc|compose|always|never)/;
 
@@ -587,6 +591,8 @@ sub parse_sendmail_aliases {
                if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) {
                        $aliases{$1} = [ $2 ];
                }}}
+       # Please update _git_config() in git-completion.bash when you
+       # add new MUAs.
 );
 
 if (@alias_files and $aliasfiletype and defined $parse_alias{$aliasfiletype}) {
index b5f2beee60ab59a04b5b236da8df39403009db1b..2c0fb6d723b74bb5bccba1ea49f97cdf23def361 100755 (executable)
@@ -5,7 +5,8 @@
 # Copyright (c) 2007 Lars Hjemli
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
-USAGE="[--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
+USAGE="[--quiet] [--cached]
+   or: $dashless [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
    or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
    or: $dashless [--quiet] init [--] [<path>...]
    or: $dashless [--quiet] deinit [-f|--force] (--all| [--] <path>...)
@@ -593,7 +594,7 @@ cmd_update()
                                # is not reachable from a ref.
                                is_tip_reachable "$sm_path" "$sha1" ||
                                fetch_in_submodule "$sm_path" $depth ||
-                               say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
+                               say "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'; trying to directly fetch \$sha1:")"
 
                                # Now we tried the usual fetch, but $sha1 may
                                # not be reachable from any of the refs
diff --git a/git.c b/git.c
index 2014aab6b83c61695d50ac39a18864a8d77858e0..181785ec479de577cfb98217ca4064e90bb95a72 100644 (file)
--- a/git.c
+++ b/git.c
@@ -62,6 +62,13 @@ static int list_cmds(const char *spec)
 {
        struct string_list list = STRING_LIST_INIT_DUP;
        int i;
+       int nongit;
+
+       /*
+       * Set up the repository so we can pick up any repo-level config (like
+       * completion.commands).
+       */
+       setup_git_directory_gently(&nongit);
 
        while (*spec) {
                const char *sep = strchrnul(spec, ',');
index 407d5550b1aba947549ad509a641134c34f28d46..87ab1fac24d6aa7a35f3bec0ac909366b43e46d9 100644 (file)
@@ -1,15 +1,15 @@
 # Bulgarian translation of gitk po-file.
-# Copyright (C) 2014, 2015 Alexander Shopov <ash@kambanaria.org>.
+# Copyright (C) 2014, 2015, 2019 Alexander Shopov <ash@kambanaria.org>.
 # This file is distributed under the same license as the git package.
-# Alexander Shopov <ash@kambanaria.org>, 2014, 2015.
+# Alexander Shopov <ash@kambanaria.org>, 2014, 2015, 2019.
 #
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: gitk master\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-12-19 11:48+0200\n"
-"PO-Revision-Date: 2015-12-19 11:49+0200\n"
+"POT-Creation-Date: 2019-03-04 11:27+0100\n"
+"PO-Revision-Date: 2019-03-04 11:39+0100\n"
 "Last-Translator: Alexander Shopov <ash@kambanaria.org>\n"
 "Language-Team: Bulgarian <dict@fsa-bg.org>\n"
 "Language: bg\n"
@@ -22,17 +22,17 @@ msgstr ""
 msgid "Couldn't get list of unmerged files:"
 msgstr "Списъкът с неслети файлове не може да бъде получен:"
 
-#: gitk:212 gitk:2399
+#: gitk:212 gitk:2403
 msgid "Color words"
 msgstr "Оцветяване на думите"
 
-#: gitk:217 gitk:2399 gitk:8239 gitk:8272
+#: gitk:217 gitk:2403 gitk:8249 gitk:8282
 msgid "Markup words"
 msgstr "Отбелязване на думите"
 
 #: gitk:324
 msgid "Error parsing revisions:"
-msgstr "Грешка при разбор на версиите:"
+msgstr "Грешка при анализ на версиите:"
 
 #: gitk:380
 msgid "Error executing --argscmd command:"
@@ -59,314 +59,318 @@ msgstr "Грешка при изпълнение на „git log“:"
 msgid "Reading"
 msgstr "Прочитане"
 
-#: gitk:496 gitk:4544
+#: gitk:496 gitk:4549
 msgid "Reading commits..."
 msgstr "Прочитане на подаванията…"
 
-#: gitk:499 gitk:1637 gitk:4547
+#: gitk:499 gitk:1641 gitk:4552
 msgid "No commits selected"
 msgstr "Не са избрани подавания"
 
-#: gitk:1445 gitk:4064 gitk:12469
+#: gitk:1449 gitk:4069 gitk:12583
 msgid "Command line"
 msgstr "Команден ред"
 
-#: gitk:1511
+#: gitk:1515
 msgid "Can't parse git log output:"
 msgstr "Изходът от „git log“ не може да се анализира:"
 
-#: gitk:1740
+#: gitk:1744
 msgid "No commit information available"
 msgstr "Липсва информация за подавания"
 
-#: gitk:1903 gitk:1932 gitk:4334 gitk:9702 gitk:11274 gitk:11554
+#: gitk:1907 gitk:1936 gitk:4339 gitk:9789 gitk:11388 gitk:11668
 msgid "OK"
 msgstr "Добре"
 
-#: gitk:1934 gitk:4336 gitk:9215 gitk:9294 gitk:9424 gitk:9473 gitk:9704
-#: gitk:11275 gitk:11555
+#: gitk:1938 gitk:4341 gitk:9225 gitk:9304 gitk:9434 gitk:9520 gitk:9791
+#: gitk:11389 gitk:11669
 msgid "Cancel"
 msgstr "Отказ"
 
-#: gitk:2083
+#: gitk:2087
 msgid "&Update"
 msgstr "&Обновяване"
 
-#: gitk:2084
+#: gitk:2088
 msgid "&Reload"
 msgstr "&Презареждане"
 
-#: gitk:2085
+#: gitk:2089
 msgid "Reread re&ferences"
-msgstr "&Наново прочитане на настройките"
+msgstr "&Наново прочитане"
 
-#: gitk:2086
+#: gitk:2090
 msgid "&List references"
 msgstr "&Изброяване на указателите"
 
-#: gitk:2088
+#: gitk:2092
 msgid "Start git &gui"
 msgstr "&Стартиране на „git gui“"
 
-#: gitk:2090
+#: gitk:2094
 msgid "&Quit"
 msgstr "&Спиране на програмата"
 
-#: gitk:2082
+#: gitk:2086
 msgid "&File"
 msgstr "&Файл"
 
-#: gitk:2094
+#: gitk:2098
 msgid "&Preferences"
 msgstr "&Настройки"
 
-#: gitk:2093
+#: gitk:2097
 msgid "&Edit"
 msgstr "&Редактиране"
 
-#: gitk:2098
+#: gitk:2102
 msgid "&New view..."
 msgstr "&Нов изглед…"
 
-#: gitk:2099
+#: gitk:2103
 msgid "&Edit view..."
 msgstr "&Редактиране на изгледа…"
 
-#: gitk:2100
+#: gitk:2104
 msgid "&Delete view"
 msgstr "&Изтриване на изгледа"
 
-#: gitk:2102
+#: gitk:2106
 msgid "&All files"
 msgstr "&Всички файлове"
 
-#: gitk:2097
+#: gitk:2101
 msgid "&View"
 msgstr "&Изглед"
 
-#: gitk:2107 gitk:2117
+#: gitk:2111 gitk:2121
 msgid "&About gitk"
 msgstr "&Относно gitk"
 
-#: gitk:2108 gitk:2122
+#: gitk:2112 gitk:2126
 msgid "&Key bindings"
 msgstr "&Клавишни комбинации"
 
-#: gitk:2106 gitk:2121
+#: gitk:2110 gitk:2125
 msgid "&Help"
 msgstr "Помо&щ"
 
-#: gitk:2199 gitk:8671
+#: gitk:2203 gitk:8681
 msgid "SHA1 ID:"
 msgstr "SHA1:"
 
-#: gitk:2243
+#: gitk:2247
 msgid "Row"
 msgstr "Ред"
 
-#: gitk:2281
+#: gitk:2285
 msgid "Find"
 msgstr "Търсене"
 
-#: gitk:2309
+#: gitk:2313
 msgid "commit"
 msgstr "подаване"
 
-#: gitk:2313 gitk:2315 gitk:4706 gitk:4729 gitk:4753 gitk:6774 gitk:6846
-#: gitk:6931
+#: gitk:2317 gitk:2319 gitk:4711 gitk:4734 gitk:4758 gitk:6779 gitk:6851
+#: gitk:6936
 msgid "containing:"
 msgstr "съдържащо:"
 
-#: gitk:2316 gitk:3545 gitk:3550 gitk:4782
+#: gitk:2320 gitk:3550 gitk:3555 gitk:4787
 msgid "touching paths:"
-msgstr "заÑ\81Ñ\8fгаÑ\89о пътищата:"
+msgstr "в пътищата:"
 
-#: gitk:2317 gitk:4796
+#: gitk:2321 gitk:4801
 msgid "adding/removing string:"
 msgstr "добавящо/премахващо низ"
 
-#: gitk:2318 gitk:4798
+#: gitk:2322 gitk:4803
 msgid "changing lines matching:"
 msgstr "променящо редове напасващи:"
 
-#: gitk:2327 gitk:2329 gitk:4785
+#: gitk:2331 gitk:2333 gitk:4790
 msgid "Exact"
 msgstr "Точно"
 
-#: gitk:2329 gitk:4873 gitk:6742
+#: gitk:2333 gitk:4878 gitk:6747
 msgid "IgnCase"
 msgstr "Без регистър"
 
-#: gitk:2329 gitk:4755 gitk:4871 gitk:6738
+#: gitk:2333 gitk:4760 gitk:4876 gitk:6743
 msgid "Regexp"
 msgstr "Рег. израз"
 
-#: gitk:2331 gitk:2332 gitk:4893 gitk:4923 gitk:4930 gitk:6867 gitk:6935
+#: gitk:2335 gitk:2336 gitk:4898 gitk:4928 gitk:4935 gitk:6872 gitk:6940
 msgid "All fields"
 msgstr "Всички полета"
 
-#: gitk:2332 gitk:4890 gitk:4923 gitk:6805
+#: gitk:2336 gitk:4895 gitk:4928 gitk:6810
 msgid "Headline"
 msgstr "Първи ред"
 
-#: gitk:2333 gitk:4890 gitk:6805 gitk:6935 gitk:7408
+#: gitk:2337 gitk:4895 gitk:6810 gitk:6940 gitk:7413
 msgid "Comments"
 msgstr "Коментари"
 
-#: gitk:2333 gitk:4890 gitk:4895 gitk:4930 gitk:6805 gitk:7343 gitk:8849
-#: gitk:8864
+#: gitk:2337 gitk:4895 gitk:4900 gitk:4935 gitk:6810 gitk:7348 gitk:8859
+#: gitk:8874
 msgid "Author"
 msgstr "Автор"
 
-#: gitk:2333 gitk:4890 gitk:6805 gitk:7345
+#: gitk:2337 gitk:4895 gitk:6810 gitk:7350
 msgid "Committer"
 msgstr "Подаващ"
 
-#: gitk:2367
+#: gitk:2371
 msgid "Search"
 msgstr "Търсене"
 
-#: gitk:2375
+#: gitk:2379
 msgid "Diff"
 msgstr "Разлики"
 
-#: gitk:2377
+#: gitk:2381
 msgid "Old version"
 msgstr "Стара версия"
 
-#: gitk:2379
+#: gitk:2383
 msgid "New version"
 msgstr "Нова версия"
 
-#: gitk:2382
+#: gitk:2386
 msgid "Lines of context"
 msgstr "Контекст в редове"
 
-#: gitk:2392
+#: gitk:2396
 msgid "Ignore space change"
 msgstr "Празните знаци без значение"
 
-#: gitk:2396 gitk:2398 gitk:7978 gitk:8225
+#: gitk:2400 gitk:2402 gitk:7983 gitk:8235
 msgid "Line diff"
 msgstr "Поредови разлики"
 
-#: gitk:2463
+#: gitk:2467
 msgid "Patch"
 msgstr "Кръпка"
 
-#: gitk:2465
+#: gitk:2469
 msgid "Tree"
 msgstr "Дърво"
 
-#: gitk:2635 gitk:2656
+#: gitk:2639 gitk:2660
 msgid "Diff this -> selected"
 msgstr "Разлики между това и избраното"
 
-#: gitk:2636 gitk:2657
+#: gitk:2640 gitk:2661
 msgid "Diff selected -> this"
 msgstr "Разлики между избраното и това"
 
-#: gitk:2637 gitk:2658
+#: gitk:2641 gitk:2662
 msgid "Make patch"
 msgstr "Създаване на кръпка"
 
-#: gitk:2638 gitk:9273
+#: gitk:2642 gitk:9283
 msgid "Create tag"
 msgstr "Създаване на етикет"
 
-#: gitk:2639
+#: gitk:2643
 msgid "Copy commit summary"
 msgstr "Копиране на информацията за подаване"
 
-#: gitk:2640 gitk:9404
+#: gitk:2644 gitk:9414
 msgid "Write commit to file"
 msgstr "Запазване на подаването във файл"
 
-#: gitk:2641 gitk:9461
+#: gitk:2645
 msgid "Create new branch"
 msgstr "Създаване на нов клон"
 
-#: gitk:2642
+#: gitk:2646
 msgid "Cherry-pick this commit"
 msgstr "Отбиране на това подаване"
 
-#: gitk:2643
+#: gitk:2647
 msgid "Reset HEAD branch to here"
 msgstr "Привеждане на върха на клона към текущото подаване"
 
-#: gitk:2644
+#: gitk:2648
 msgid "Mark this commit"
 msgstr "Отбелязване на това подаване"
 
-#: gitk:2645
+#: gitk:2649
 msgid "Return to mark"
 msgstr "Връщане към отбелязаното подаване"
 
-#: gitk:2646
+#: gitk:2650
 msgid "Find descendant of this and mark"
 msgstr "Откриване и отбелязване на наследниците"
 
-#: gitk:2647
+#: gitk:2651
 msgid "Compare with marked commit"
 msgstr "Сравнение с отбелязаното подаване"
 
-#: gitk:2648 gitk:2659
+#: gitk:2652 gitk:2663
 msgid "Diff this -> marked commit"
 msgstr "Разлики между това и отбелязаното"
 
-#: gitk:2649 gitk:2660
+#: gitk:2653 gitk:2664
 msgid "Diff marked commit -> this"
 msgstr "Разлики между отбелязаното и това"
 
-#: gitk:2650
+#: gitk:2654
 msgid "Revert this commit"
 msgstr "Отмяна на това подаване"
 
-#: gitk:2666
+#: gitk:2670
 msgid "Check out this branch"
 msgstr "Изтегляне на този клон"
 
-#: gitk:2667
+#: gitk:2671
+msgid "Rename this branch"
+msgstr "Преименуване на този клон"
+
+#: gitk:2672
 msgid "Remove this branch"
 msgstr "Изтриване на този клон"
 
-#: gitk:2668
+#: gitk:2673
 msgid "Copy branch name"
 msgstr "Копиране на името на клона"
 
-#: gitk:2675
+#: gitk:2680
 msgid "Highlight this too"
 msgstr "Отбелязване и на това"
 
-#: gitk:2676
+#: gitk:2681
 msgid "Highlight this only"
 msgstr "Отбелязване само на това"
 
-#: gitk:2677
+#: gitk:2682
 msgid "External diff"
 msgstr "Външна програма за разлики"
 
-#: gitk:2678
+#: gitk:2683
 msgid "Blame parent commit"
 msgstr "Анотиране на родителското подаване"
 
-#: gitk:2679
+#: gitk:2684
 msgid "Copy path"
 msgstr "Копиране на пътя"
 
-#: gitk:2686
+#: gitk:2691
 msgid "Show origin of this line"
 msgstr "Показване на произхода на този ред"
 
-#: gitk:2687
+#: gitk:2692
 msgid "Run git gui blame on this line"
 msgstr "Изпълнение на „git gui blame“ върху този ред"
 
-#: gitk:3031
+#: gitk:3036
 msgid "About gitk"
 msgstr "Относно gitk"
 
-#: gitk:3033
+#: gitk:3038
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -382,324 +386,324 @@ msgstr ""
 "\n"
 "Използвайте и разпространявайте при условията на ОПЛ на ГНУ"
 
-#: gitk:3041 gitk:3108 gitk:9890
+#: gitk:3046 gitk:3113 gitk:10004
 msgid "Close"
 msgstr "Затваряне"
 
-#: gitk:3062
+#: gitk:3067
 msgid "Gitk key bindings"
 msgstr "Клавишни комбинации"
 
-#: gitk:3065
+#: gitk:3070
 msgid "Gitk key bindings:"
 msgstr "Клавишни комбинации:"
 
-#: gitk:3067
+#: gitk:3072
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tСпиране на програмата"
 
-#: gitk:3068
+#: gitk:3073
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tЗатваряне на прозореца"
 
-#: gitk:3069
+#: gitk:3074
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tКъм първото подаване"
 
-#: gitk:3070
+#: gitk:3075
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tКъм последното подаване"
 
-#: gitk:3071
+#: gitk:3076
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Up>, p, k\tЕдно подаване нагоре"
 
-#: gitk:3072
+#: gitk:3077
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Down>, n, j\tЕдно подаване надолу"
 
-#: gitk:3073
+#: gitk:3078
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Left>, z, h\tНазад в историята"
 
-#: gitk:3074
+#: gitk:3079
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Right>, x, l\tНапред в историята"
 
-#: gitk:3075
+#: gitk:3080
 #, tcl-format
 msgid "<%s-n>\tGo to n-th parent of current commit in history list"
 msgstr "<%s-n>\tКъм n-тия родител на текущото подаване в историята"
 
-#: gitk:3076
+#: gitk:3081
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tСтраница нагоре в списъка с подаванията"
 
-#: gitk:3077
+#: gitk:3082
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tСтраница надолу в списъка с подаванията"
 
-#: gitk:3078
+#: gitk:3083
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tКъм началото на списъка с подаванията"
 
-#: gitk:3079
+#: gitk:3084
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tКъм края на списъка с подаванията"
 
-#: gitk:3080
+#: gitk:3085
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Up>\tРед нагоре в списъка с подавания"
 
-#: gitk:3081
+#: gitk:3086
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Down>\tРед надолу в списъка с подавания"
 
-#: gitk:3082
+#: gitk:3087
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tСтраница нагоре в списъка с подавания"
 
-#: gitk:3083
+#: gitk:3088
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tСтраница надолу в списъка с подавания"
 
-#: gitk:3084
+#: gitk:3089
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Shift-Up>\tТърсене назад (визуално нагоре, исторически — последващи)"
 
-#: gitk:3085
+#: gitk:3090
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr ""
 "<Shift-Down>\tТърсене напред (визуално надолу, исторически — предхождащи)"
 
-#: gitk:3086
+#: gitk:3091
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tСтраница нагоре в изгледа за разлики"
 
-#: gitk:3087
+#: gitk:3092
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Backspace>\tСтраница надолу в изгледа за разлики"
 
-#: gitk:3088
+#: gitk:3093
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Space>\t\tСтраница надолу в изгледа за разлики"
 
-#: gitk:3089
+#: gitk:3094
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\t18 реда нагоре в изгледа за разлики"
 
-#: gitk:3090
+#: gitk:3095
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\t18 реда надолу в изгледа за разлики"
 
-#: gitk:3091
+#: gitk:3096
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tТърсене"
 
-#: gitk:3092
+#: gitk:3097
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tКъм следващата поява"
 
-#: gitk:3093
+#: gitk:3098
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\tКъм следващата поява"
 
-#: gitk:3094
+#: gitk:3099
 msgid "g\t\tGo to commit"
 msgstr "g\t\tКъм последното подаване"
 
-#: gitk:3095
+#: gitk:3100
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tФокус върху полето за търсене"
 
-#: gitk:3096
+#: gitk:3101
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tКъм предишната поява"
 
-#: gitk:3097
+#: gitk:3102
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tСледващ файл в изгледа за разлики"
 
-#: gitk:3098
+#: gitk:3103
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tТърсене на следващата поява в изгледа за разлики"
 
-#: gitk:3099
+#: gitk:3104
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tТърсене на предишната поява в изгледа за разлики"
 
-#: gitk:3100
+#: gitk:3105
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-KP+>\tПо-голям размер на шрифта"
 
-#: gitk:3101
+#: gitk:3106
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tПо-голям размер на шрифта"
 
-#: gitk:3102
+#: gitk:3107
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-KP->\tПо-малък размер на шрифта"
 
-#: gitk:3103
+#: gitk:3108
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tПо-малък размер на шрифта"
 
-#: gitk:3104
+#: gitk:3109
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tОбновяване"
 
-#: gitk:3569 gitk:3578
+#: gitk:3574 gitk:3583
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Грешка при създаването на временната директория „%s“:"
 
-#: gitk:3591
+#: gitk:3596
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Грешка при получаването на „%s“ от %s:"
 
-#: gitk:3654
+#: gitk:3659
 msgid "command failed:"
 msgstr "неуспешно изпълнение на команда:"
 
-#: gitk:3803
+#: gitk:3808
 msgid "No such commit"
 msgstr "Такова подаване няма"
 
-#: gitk:3817
+#: gitk:3822
 msgid "git gui blame: command failed:"
 msgstr "„git gui blame“: неуспешно изпълнение на команда:"
 
-#: gitk:3848
+#: gitk:3853
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Върхът за сливане не може да бъде прочетен: %s"
 
-#: gitk:3856
+#: gitk:3861
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Грешка при прочитане на индекса: %s"
 
-#: gitk:3881
+#: gitk:3886
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Командата „git blame“ не може да бъде стартирана: %s"
 
-#: gitk:3884 gitk:6773
+#: gitk:3889 gitk:6778
 msgid "Searching"
 msgstr "Търсене"
 
-#: gitk:3916
+#: gitk:3921
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Грешка при изпълнението на „git blame“: %s"
 
-#: gitk:3944
+#: gitk:3949
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Този ред идва от подаването %s, което не е в изгледа"
 
-#: gitk:3958
+#: gitk:3963
 msgid "External diff viewer failed:"
 msgstr "Неуспешно изпълнение на външната програма за разлики:"
 
-#: gitk:4062
+#: gitk:4067
 msgid "All files"
 msgstr "Всички файлове"
 
-#: gitk:4086
+#: gitk:4091
 msgid "View"
 msgstr "Изглед"
 
-#: gitk:4089
+#: gitk:4094
 msgid "Gitk view definition"
 msgstr "Дефиниция на изглед в Gitk"
 
-#: gitk:4093
+#: gitk:4098
 msgid "Remember this view"
 msgstr "Запазване на този изглед"
 
-#: gitk:4094
+#: gitk:4099
 msgid "References (space separated list):"
 msgstr "Указатели (списък с разделител интервал):"
 
-#: gitk:4095
+#: gitk:4100
 msgid "Branches & tags:"
 msgstr "Клони и етикети:"
 
-#: gitk:4096
+#: gitk:4101
 msgid "All refs"
 msgstr "Всички указатели"
 
-#: gitk:4097
+#: gitk:4102
 msgid "All (local) branches"
 msgstr "Всички (локални) клони"
 
-#: gitk:4098
+#: gitk:4103
 msgid "All tags"
 msgstr "Всички етикети"
 
-#: gitk:4099
+#: gitk:4104
 msgid "All remote-tracking branches"
 msgstr "Всички следящи клони"
 
-#: gitk:4100
+#: gitk:4105
 msgid "Commit Info (regular expressions):"
 msgstr "Информация за подаване (рег. изр.):"
 
-#: gitk:4101
+#: gitk:4106
 msgid "Author:"
 msgstr "Автор:"
 
-#: gitk:4102
+#: gitk:4107
 msgid "Committer:"
 msgstr "Подал:"
 
-#: gitk:4103
+#: gitk:4108
 msgid "Commit Message:"
 msgstr "Съобщение при подаване:"
 
-#: gitk:4104
+#: gitk:4109
 msgid "Matches all Commit Info criteria"
 msgstr "Съвпадение по всички характеристики на подаването"
 
-#: gitk:4105
+#: gitk:4110
 msgid "Matches no Commit Info criteria"
 msgstr "Не съвпада по никоя от характеристиките на подаването"
 
-#: gitk:4106
+#: gitk:4111
 msgid "Changes to Files:"
 msgstr "Промени по файловете:"
 
-#: gitk:4107
+#: gitk:4112
 msgid "Fixed String"
 msgstr "Дословен низ"
 
-#: gitk:4108
+#: gitk:4113
 msgid "Regular Expression"
 msgstr "Регулярен израз"
 
-#: gitk:4109
+#: gitk:4114
 msgid "Search string:"
 msgstr "Низ за търсене:"
 
-#: gitk:4110
+#: gitk:4115
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -707,204 +711,204 @@ msgstr ""
 "Дата на подаване („2 weeks ago“ (преди 2 седмици), „2009-03-17 15:27:38“, "
 "„March 17, 2009 15:27:38“):"
 
-#: gitk:4111
+#: gitk:4116
 msgid "Since:"
 msgstr "От:"
 
-#: gitk:4112
+#: gitk:4117
 msgid "Until:"
 msgstr "До:"
 
-#: gitk:4113
+#: gitk:4118
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr ""
 "Ограничаване и/или прескачане на определен брой версии (неотрицателно цяло "
 "число):"
 
-#: gitk:4114
+#: gitk:4119
 msgid "Number to show:"
 msgstr "Брой показани:"
 
-#: gitk:4115
+#: gitk:4120
 msgid "Number to skip:"
 msgstr "Брой прескочени:"
 
-#: gitk:4116
+#: gitk:4121
 msgid "Miscellaneous options:"
 msgstr "Разни:"
 
-#: gitk:4117
+#: gitk:4122
 msgid "Strictly sort by date"
 msgstr "Подреждане по дата"
 
-#: gitk:4118
+#: gitk:4123
 msgid "Mark branch sides"
 msgstr "Отбелязване на страните по клона"
 
-#: gitk:4119
+#: gitk:4124
 msgid "Limit to first parent"
 msgstr "Само първия родител"
 
-#: gitk:4120
+#: gitk:4125
 msgid "Simple history"
 msgstr "Опростена история"
 
-#: gitk:4121
+#: gitk:4126
 msgid "Additional arguments to git log:"
 msgstr "Допълнителни аргументи към „git log“:"
 
-#: gitk:4122
+#: gitk:4127
 msgid "Enter files and directories to include, one per line:"
 msgstr "Въведете файловете и директориите за включване, по елемент на ред"
 
-#: gitk:4123
+#: gitk:4128
 msgid "Command to generate more commits to include:"
 msgstr ""
 "Команда за генерирането на допълнителни подавания, които да бъдат включени:"
 
-#: gitk:4247
+#: gitk:4252
 msgid "Gitk: edit view"
 msgstr "Gitk: редактиране на изглед"
 
-#: gitk:4255
+#: gitk:4260
 msgid "-- criteria for selecting revisions"
 msgstr "— критерии за избор на версии"
 
-#: gitk:4260
+#: gitk:4265
 msgid "View Name"
 msgstr "Име на изглед"
 
-#: gitk:4335
+#: gitk:4340
 msgid "Apply (F5)"
 msgstr "Прилагане (F5)"
 
-#: gitk:4373
+#: gitk:4378
 msgid "Error in commit selection arguments:"
 msgstr "Грешка в аргументите за избор на подавания:"
 
-#: gitk:4428 gitk:4481 gitk:4943 gitk:4957 gitk:6227 gitk:12410 gitk:12411
+#: gitk:4433 gitk:4486 gitk:4948 gitk:4962 gitk:6232 gitk:12524 gitk:12525
 msgid "None"
 msgstr "Няма"
 
-#: gitk:5040 gitk:5045
+#: gitk:5045 gitk:5050
 msgid "Descendant"
 msgstr "Наследник"
 
-#: gitk:5041
+#: gitk:5046
 msgid "Not descendant"
 msgstr "Не е наследник"
 
-#: gitk:5048 gitk:5053
+#: gitk:5053 gitk:5058
 msgid "Ancestor"
 msgstr "Предшественик"
 
-#: gitk:5049
+#: gitk:5054
 msgid "Not ancestor"
 msgstr "Не е предшественик"
 
-#: gitk:5343
+#: gitk:5348
 msgid "Local changes checked in to index but not committed"
 msgstr "Локални промени добавени към индекса, но неподадени"
 
-#: gitk:5379
+#: gitk:5384
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Локални промени извън индекса"
 
-#: gitk:7153
+#: gitk:7158
 msgid "and many more"
 msgstr "и още много"
 
-#: gitk:7156
+#: gitk:7161
 msgid "many"
 msgstr "много"
 
-#: gitk:7347
+#: gitk:7352
 msgid "Tags:"
 msgstr "Етикети:"
 
-#: gitk:7364 gitk:7370 gitk:8844
+#: gitk:7369 gitk:7375 gitk:8854
 msgid "Parent"
 msgstr "Родител"
 
-#: gitk:7375
+#: gitk:7380
 msgid "Child"
 msgstr "Дете"
 
-#: gitk:7384
+#: gitk:7389
 msgid "Branch"
 msgstr "Клон"
 
-#: gitk:7387
+#: gitk:7392
 msgid "Follows"
 msgstr "Следва"
 
-#: gitk:7390
+#: gitk:7395
 msgid "Precedes"
 msgstr "Предшества"
 
-#: gitk:7985
+#: gitk:7990
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Грешка при получаването на разликите: %s"
 
-#: gitk:8669
+#: gitk:8679
 msgid "Goto:"
 msgstr "Към ред:"
 
-#: gitk:8690
+#: gitk:8700
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Съкратената сума по SHA1 %s не е еднозначна"
 
-#: gitk:8697
+#: gitk:8707
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Непозната версия %s"
 
-#: gitk:8707
+#: gitk:8717
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "Непозната сума по SHA1 %s"
 
-#: gitk:8709
+#: gitk:8719
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "Версия %s не е в текущия изглед"
 
-#: gitk:8851 gitk:8866
+#: gitk:8861 gitk:8876
 msgid "Date"
 msgstr "Дата"
 
-#: gitk:8854
+#: gitk:8864
 msgid "Children"
 msgstr "Деца"
 
-#: gitk:8917
+#: gitk:8927
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Зануляване на клона „%s“ към текущото подаване"
 
-#: gitk:8919
+#: gitk:8929
 msgid "Detached head: can't reset"
 msgstr "Несвързан връх: невъзможно зануляване"
 
-#: gitk:9024 gitk:9030
+#: gitk:9034 gitk:9040
 msgid "Skipping merge commit "
 msgstr "Пропускане на подаването на сливането"
 
-#: gitk:9039 gitk:9044
+#: gitk:9049 gitk:9054
 msgid "Error getting patch ID for "
 msgstr "Грешка при получаването на идентификатора на "
 
-#: gitk:9040 gitk:9045
+#: gitk:9050 gitk:9055
 msgid " - stopping\n"
 msgstr " — спиране\n"
 
-#: gitk:9050 gitk:9053 gitk:9061 gitk:9075 gitk:9084
+#: gitk:9060 gitk:9063 gitk:9071 gitk:9085 gitk:9094
 msgid "Commit "
 msgstr "Подаване"
 
-#: gitk:9054
+#: gitk:9064
 msgid ""
 " is the same patch as\n"
 "       "
@@ -912,7 +916,7 @@ msgstr ""
 " е същата кръпка като\n"
 "       "
 
-#: gitk:9062
+#: gitk:9072
 msgid ""
 " differs from\n"
 "       "
@@ -920,7 +924,7 @@ msgstr ""
 " се различава от\n"
 "       "
 
-#: gitk:9064
+#: gitk:9074
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -928,130 +932,147 @@ msgstr ""
 "Разлика между подаванията:\n"
 "\n"
 
-#: gitk:9076 gitk:9085
+#: gitk:9086 gitk:9095
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " има %s деца — спиране\n"
 
-#: gitk:9104
+#: gitk:9114
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Грешка при запазването на подаването във файл: %s"
 
-#: gitk:9110
+#: gitk:9120
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Грешка при изчисляването на разликите между подаванията: %s"
 
-#: gitk:9156
+#: gitk:9166
 msgid "Top"
 msgstr "Най-горе"
 
-#: gitk:9157
+#: gitk:9167
 msgid "From"
 msgstr "От"
 
-#: gitk:9162
+#: gitk:9172
 msgid "To"
 msgstr "До"
 
-#: gitk:9186
+#: gitk:9196
 msgid "Generate patch"
 msgstr "Генериране на кръпка"
 
-#: gitk:9188
+#: gitk:9198
 msgid "From:"
 msgstr "От:"
 
-#: gitk:9197
+#: gitk:9207
 msgid "To:"
 msgstr "До:"
 
-#: gitk:9206
+#: gitk:9216
 msgid "Reverse"
 msgstr "Обръщане"
 
-#: gitk:9208 gitk:9418
+#: gitk:9218 gitk:9428
 msgid "Output file:"
 msgstr "Запазване във файла:"
 
-#: gitk:9214
+#: gitk:9224
 msgid "Generate"
 msgstr "Генериране"
 
-#: gitk:9252
+#: gitk:9262
 msgid "Error creating patch:"
 msgstr "Грешка при създаването на кръпка:"
 
-#: gitk:9275 gitk:9406 gitk:9463
+#: gitk:9285 gitk:9416 gitk:9504
 msgid "ID:"
 msgstr "Идентификатор:"
 
-#: gitk:9284
+#: gitk:9294
 msgid "Tag name:"
 msgstr "Име на етикет:"
 
-#: gitk:9287
+#: gitk:9297
 msgid "Tag message is optional"
 msgstr "Съобщението за етикет е незадължително"
 
-#: gitk:9289
+#: gitk:9299
 msgid "Tag message:"
 msgstr "Съобщение за етикет:"
 
-#: gitk:9293 gitk:9472
+#: gitk:9303 gitk:9474
 msgid "Create"
 msgstr "Създаване"
 
-#: gitk:9311
+#: gitk:9321
 msgid "No tag name specified"
 msgstr "Липсва име на етикет"
 
-#: gitk:9315
+#: gitk:9325
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Етикетът „%s“ вече съществува"
 
-#: gitk:9325
+#: gitk:9335
 msgid "Error creating tag:"
 msgstr "Грешка при създаването на етикет:"
 
-#: gitk:9415
+#: gitk:9425
 msgid "Command:"
 msgstr "Команда:"
 
-#: gitk:9423
+#: gitk:9433
 msgid "Write"
 msgstr "Запазване"
 
-#: gitk:9441
+#: gitk:9451
 msgid "Error writing commit:"
 msgstr "Грешка при запазването на подаването:"
 
-#: gitk:9468
+#: gitk:9473
+msgid "Create branch"
+msgstr "Създаване на клон"
+
+#: gitk:9489
+#, tcl-format
+msgid "Rename branch %s"
+msgstr "Преименуване на клона „%s“"
+
+#: gitk:9490
+msgid "Rename"
+msgstr "Преименуване"
+
+#: gitk:9514
 msgid "Name:"
 msgstr "Име:"
 
-#: gitk:9491
+#: gitk:9538
 msgid "Please specify a name for the new branch"
 msgstr "Укажете име за новия клон"
 
-#: gitk:9496
+#: gitk:9543
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Клонът „%s“ вече съществува. Да бъде ли презаписан?"
 
-#: gitk:9563
+#: gitk:9587
+msgid "Please specify a new name for the branch"
+msgstr "Укажете ново име за клона"
+
+#: gitk:9650
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Подаването „%s“ вече е включено в клона „%s“ — да бъде ли приложено отново?"
 
-#: gitk:9568
+#: gitk:9655
 msgid "Cherry-picking"
 msgstr "Отбиране"
 
-#: gitk:9577
+#: gitk:9664
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1060,7 +1081,7 @@ msgstr ""
 "Неуспешно отбиране, защото във файла „%s“ има локални промени.\n"
 "Подайте, занулете или ги скатайте и пробвайте отново."
 
-#: gitk:9583
+#: gitk:9670
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1068,29 +1089,29 @@ msgstr ""
 "Неуспешно отбиране поради конфликти при сливане.\n"
 "Искате ли да ги коригирате чрез „git citool“?"
 
-#: gitk:9599 gitk:9657
+#: gitk:9686 gitk:9744
 msgid "No changes committed"
 msgstr "Не са подадени промени"
 
-#: gitk:9626
+#: gitk:9713
 #, tcl-format
 msgid "Commit %s is not included in branch %s -- really revert it?"
 msgstr "Подаването „%s“ не е включено в клона „%s“. Да бъде ли отменено?"
 
-#: gitk:9631
+#: gitk:9718
 msgid "Reverting"
 msgstr "Отмяна"
 
-#: gitk:9639
+#: gitk:9726
 #, tcl-format
 msgid ""
 "Revert failed because of local changes to the following files:%s Please "
 "commit, reset or stash  your changes and try again."
 msgstr ""
 "Неуспешна отмяна, защото във файла „%s“ има локални промени.\n"
-"Подайте, занулете или ги скатайте и пробвайте отново.<"
+"Подайте, занулете или ги скатайте и пробвайте отново."
 
-#: gitk:9643
+#: gitk:9730
 msgid ""
 "Revert failed because of merge conflict.\n"
 " Do you wish to run git citool to resolve it?"
@@ -1098,66 +1119,71 @@ msgstr ""
 "Неуспешно отмяна поради конфликти при сливане.\n"
 "Искате ли да ги коригирате чрез „git citool“?"
 
-#: gitk:9686
+#: gitk:9773
 msgid "Confirm reset"
 msgstr "Потвърждаване на зануляването"
 
-#: gitk:9688
+#: gitk:9775
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Да се занули ли клонът „%s“ към „%s“?"
 
-#: gitk:9690
+#: gitk:9777
 msgid "Reset type:"
 msgstr "Вид зануляване:"
 
-#: gitk:9693
+#: gitk:9780
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Слабо: работното дърво и индекса остават същите"
 
-#: gitk:9696
+#: gitk:9783
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Смесено: работното дърво остава същото, индексът се занулява"
 
-#: gitk:9699
+#: gitk:9786
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
 msgstr ""
 "Силно: зануляване и на работното дърво, и на индекса\n"
-"(*ВСИЧКИ* локални промени ще бъдат безвъзвратно загубени)"
+"(ВСИЧКИ локални промени ще бъдат безвъзвратно загубени)"
 
-#: gitk:9716
+#: gitk:9803
 msgid "Resetting"
 msgstr "Зануляване"
 
-#: gitk:9776
+#: gitk:9876
+#, tcl-format
+msgid "A local branch named %s exists already"
+msgstr "Вече съществува локален клон „%s“."
+
+#: gitk:9884
 msgid "Checking out"
 msgstr "Изтегляне"
 
-#: gitk:9829
+#: gitk:9943
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Текущо изтегленият клон не може да бъде изтрит"
 
-#: gitk:9835
+#: gitk:9949
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
 "Really delete branch %s?"
 msgstr ""
 "Подаванията на клона „%s“ не са на никой друг клон.\n"
-"Ð\9dаиÑ\81Ñ\82ина Ð»Ð¸ Ð´Ð° Ñ\81е Ð¸Ð·Ñ\82Ñ\80ие ÐºÐ»Ð¾Ð½Ñ\8aÑ\82 „%s“?"
+"Ð\9dаиÑ\81Ñ\82ина Ð»Ð¸ Ð¸Ñ\81каÑ\82е Ð´Ð° Ð¸Ð·Ñ\82Ñ\80иеÑ\82е ÐºÐ»Ð¾Ð½Ð° „%s“?"
 
-#: gitk:9866
+#: gitk:9980
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Етикети и върхове: %s"
 
-#: gitk:9883
+#: gitk:9997
 msgid "Filter"
 msgstr "Филтриране"
 
-#: gitk:10179
+#: gitk:10293
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1165,201 +1191,201 @@ msgstr ""
 "Грешка при прочитането на топологията на подаванията. Информацията за клона "
 "и предшестващите/следващите етикети ще е непълна."
 
-#: gitk:11156
+#: gitk:11270
 msgid "Tag"
 msgstr "Етикет"
 
-#: gitk:11160
+#: gitk:11274
 msgid "Id"
 msgstr "Идентификатор"
 
-#: gitk:11243
+#: gitk:11357
 msgid "Gitk font chooser"
 msgstr "Избор на шрифт за Gitk"
 
-#: gitk:11260
+#: gitk:11374
 msgid "B"
 msgstr "Ч"
 
-#: gitk:11263
+#: gitk:11377
 msgid "I"
 msgstr "К"
 
-#: gitk:11381
+#: gitk:11495
 msgid "Commit list display options"
 msgstr "Настройки на списъка с подавания"
 
-#: gitk:11384
+#: gitk:11498
 msgid "Maximum graph width (lines)"
 msgstr "Максимална широчина на графа (в редове)"
 
-#: gitk:11388
+#: gitk:11502
 #, no-tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Максимална широчина на графа (% от панела)"
 
-#: gitk:11391
+#: gitk:11505
 msgid "Show local changes"
 msgstr "Показване на локалните промени"
 
-#: gitk:11394
+#: gitk:11508
 msgid "Auto-select SHA1 (length)"
 msgstr "Автоматично избиране на SHA1 (дължина)"
 
-#: gitk:11398
+#: gitk:11512
 msgid "Hide remote refs"
 msgstr "Скриване на отдалечените указатели"
 
-#: gitk:11402
+#: gitk:11516
 msgid "Diff display options"
 msgstr "Настройки на показването на разликите"
 
-#: gitk:11404
+#: gitk:11518
 msgid "Tab spacing"
 msgstr "Широчина на табулатора"
 
-#: gitk:11407
+#: gitk:11521
 msgid "Display nearby tags/heads"
 msgstr "Извеждане на близките етикети и върхове"
 
-#: gitk:11410
+#: gitk:11524
 msgid "Maximum # tags/heads to show"
 msgstr "Максимален брой етикети/върхове за показване"
 
-#: gitk:11413
+#: gitk:11527
 msgid "Limit diffs to listed paths"
 msgstr "Разлика само в избраните пътища"
 
-#: gitk:11416
+#: gitk:11530
 msgid "Support per-file encodings"
 msgstr "Поддръжка на различни кодирания за всеки файл"
 
-#: gitk:11422 gitk:11569
+#: gitk:11536 gitk:11683
 msgid "External diff tool"
 msgstr "Външен инструмент за разлики"
 
-#: gitk:11423
+#: gitk:11537
 msgid "Choose..."
 msgstr "Избор…"
 
-#: gitk:11428
+#: gitk:11542
 msgid "General options"
 msgstr "Общи настройки"
 
-#: gitk:11431
+#: gitk:11545
 msgid "Use themed widgets"
 msgstr "Използване на тема за графичните обекти"
 
-#: gitk:11433
+#: gitk:11547
 msgid "(change requires restart)"
 msgstr "(промяната изисква рестартиране на Gitk)"
 
-#: gitk:11435
+#: gitk:11549
 msgid "(currently unavailable)"
 msgstr "(в момента недостъпно)"
 
-#: gitk:11446
+#: gitk:11560
 msgid "Colors: press to choose"
 msgstr "Цветове: избира се с натискане"
 
-#: gitk:11449
+#: gitk:11563
 msgid "Interface"
 msgstr "Интерфейс"
 
-#: gitk:11450
+#: gitk:11564
 msgid "interface"
 msgstr "интерфейс"
 
-#: gitk:11453
+#: gitk:11567
 msgid "Background"
 msgstr "Фон"
 
-#: gitk:11454 gitk:11484
+#: gitk:11568 gitk:11598
 msgid "background"
 msgstr "фон"
 
-#: gitk:11457
+#: gitk:11571
 msgid "Foreground"
 msgstr "Знаци"
 
-#: gitk:11458
+#: gitk:11572
 msgid "foreground"
 msgstr "знаци"
 
-#: gitk:11461
+#: gitk:11575
 msgid "Diff: old lines"
 msgstr "Разлика: стари редове"
 
-#: gitk:11462
+#: gitk:11576
 msgid "diff old lines"
 msgstr "разлика, стари редове"
 
-#: gitk:11466
+#: gitk:11580
 msgid "Diff: new lines"
 msgstr "Разлика: нови редове"
 
-#: gitk:11467
+#: gitk:11581
 msgid "diff new lines"
 msgstr "разлика, нови редове"
 
-#: gitk:11471
+#: gitk:11585
 msgid "Diff: hunk header"
 msgstr "Разлика: начало на парче"
 
-#: gitk:11473
+#: gitk:11587
 msgid "diff hunk header"
 msgstr "разлика, начало на парче"
 
-#: gitk:11477
+#: gitk:11591
 msgid "Marked line bg"
 msgstr "Фон на отбелязан ред"
 
-#: gitk:11479
+#: gitk:11593
 msgid "marked line background"
 msgstr "фон на отбелязан ред"
 
-#: gitk:11483
+#: gitk:11597
 msgid "Select bg"
 msgstr "Избор на фон"
 
-#: gitk:11492
+#: gitk:11606
 msgid "Fonts: press to choose"
 msgstr "Шрифтове: избира се с натискане"
 
-#: gitk:11494
+#: gitk:11608
 msgid "Main font"
 msgstr "Основен шрифт"
 
-#: gitk:11495
+#: gitk:11609
 msgid "Diff display font"
 msgstr "Шрифт за разликите"
 
-#: gitk:11496
+#: gitk:11610
 msgid "User interface font"
 msgstr "Шрифт на интерфейса"
 
-#: gitk:11518
+#: gitk:11632
 msgid "Gitk preferences"
 msgstr "Настройки на Gitk"
 
-#: gitk:11527
+#: gitk:11641
 msgid "General"
 msgstr "Общи"
 
-#: gitk:11528
+#: gitk:11642
 msgid "Colors"
 msgstr "Цветове"
 
-#: gitk:11529
+#: gitk:11643
 msgid "Fonts"
 msgstr "Шрифтове"
 
-#: gitk:11579
+#: gitk:11693
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: избор на цвят на „%s“"
 
-#: gitk:12092
+#: gitk:12206
 msgid ""
 "Sorry, gitk cannot run with this version of Tcl/Tk.\n"
 " Gitk requires at least Tcl/Tk 8.4."
@@ -1367,15 +1393,15 @@ msgstr ""
 "Тази версия на Tcl/Tk не се поддържа от Gitk.\n"
 " Необходима ви е поне Tcl/Tk 8.4."
 
-#: gitk:12302
+#: gitk:12416
 msgid "Cannot find a git repository here."
 msgstr "Тук липсва хранилище на Git."
 
-#: gitk:12349
+#: gitk:12463
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Нееднозначен аргумент „%s“: има и такава версия, и такъв файл"
 
-#: gitk:12361
+#: gitk:12475
 msgid "Bad arguments to gitk:"
 msgstr "Неправилни аргументи на gitk:"
diff --git a/help.c b/help.c
index 520c9080e8e4abf7793af0966588aa370f09d316..a9e451f2ee7a165eecb17746db9cc1a2f7e2cfbb 100644 (file)
--- a/help.c
+++ b/help.c
@@ -375,13 +375,6 @@ void list_cmds_by_config(struct string_list *list)
 {
        const char *cmd_list;
 
-       /*
-        * There's no actual repository setup at this point (and even
-        * if there is, we don't really care; only global config
-        * matters). If we accidentally set up a repository, it's ok
-        * too since the caller (git --list-cmds=) should exit shortly
-        * anyway.
-        */
        if (git_config_get_string_const("completion.commands", &cmd_list))
                return;
 
@@ -393,8 +386,8 @@ void list_cmds_by_config(struct string_list *list)
                const char *p = strchrnul(cmd_list, ' ');
 
                strbuf_add(&sb, cmd_list, p - cmd_list);
-               if (*cmd_list == '-')
-                       string_list_remove(list, cmd_list + 1, 0);
+               if (sb.buf[0] == '-')
+                       string_list_remove(list, sb.buf + 1, 0);
                else
                        string_list_insert(list, sb.buf);
                strbuf_release(&sb);
index 24e21731c4315f414578b33178a7b784176bb24d..59248e37cc3cec8fd309df77fb58b09c8612f336 100644 (file)
@@ -1103,10 +1103,12 @@ static int process_all_files(struct line_log_data **range_out,
 
 int line_log_print(struct rev_info *rev, struct commit *commit)
 {
-       struct line_log_data *range = lookup_line_range(rev, commit);
 
        show_log(rev);
-       dump_diff_hacky(rev, range);
+       if (!(rev->diffopt.output_format & DIFF_FORMAT_NO_OUTPUT)) {
+               struct line_log_data *range = lookup_line_range(rev, commit);
+               dump_diff_hacky(rev, range);
+       }
        return 1;
 }
 
index b71bd1fb65bc6b9d6c6889b7dcf8d210d57f1e53..c0036f73789d1a6a3ff88a76c3838241e65ca868 100644 (file)
@@ -82,6 +82,10 @@ static int gently_parse_list_objects_filter(
                filter_options->sparse_path_value = strdup(v0);
                return 0;
        }
+       /*
+        * Please update _git_fetch() in git-completion.bash when you
+        * add new filters
+        */
 
        if (errbuf)
                strbuf_addf(errbuf, "invalid filter-spec '%s'", arg);
index 4851825aebf29d129aa4b82d860adcbb2697a300..6c40c61c4728d9224006768599d7bf2ded744bb1 100644 (file)
@@ -1402,8 +1402,7 @@ static int merge_mode_and_contents(struct merge_options *o,
 
 static int handle_rename_via_dir(struct merge_options *o,
                                 struct diff_filepair *pair,
-                                const char *rename_branch,
-                                const char *other_branch)
+                                const char *rename_branch)
 {
        /*
         * Handle file adds that need to be renamed due to directory rename
@@ -2213,8 +2212,7 @@ static void handle_directory_level_conflicts(struct merge_options *o,
        remove_hashmap_entries(dir_re_merge, &remove_from_merge);
 }
 
-static struct hashmap *get_directory_renames(struct diff_queue_struct *pairs,
-                                            struct tree *tree)
+static struct hashmap *get_directory_renames(struct diff_queue_struct *pairs)
 {
        struct hashmap *dir_renames;
        struct hashmap_iter iter;
@@ -2460,8 +2458,7 @@ static void apply_directory_rename_modifications(struct merge_options *o,
                                                 struct tree *o_tree,
                                                 struct tree *a_tree,
                                                 struct tree *b_tree,
-                                                struct string_list *entries,
-                                                int *clean)
+                                                struct string_list *entries)
 {
        struct string_list_item *item;
        int stage = (tree == a_tree ? 2 : 3);
@@ -2632,8 +2629,7 @@ static struct string_list *get_renames(struct merge_options *o,
                        apply_directory_rename_modifications(o, pair, new_path,
                                                             re, tree, o_tree,
                                                             a_tree, b_tree,
-                                                            entries,
-                                                            clean_merge);
+                                                            entries);
        }
 
        hashmap_iter_init(&collisions, &iter);
@@ -2944,8 +2940,8 @@ static int detect_and_process_renames(struct merge_options *o,
        merge_pairs = get_diffpairs(o, common, merge);
 
        if (o->detect_directory_renames) {
-               dir_re_head = get_directory_renames(head_pairs, head);
-               dir_re_merge = get_directory_renames(merge_pairs, merge);
+               dir_re_head = get_directory_renames(head_pairs);
+               dir_re_merge = get_directory_renames(merge_pairs);
 
                handle_directory_level_conflicts(o,
                                                 dir_re_head, head,
@@ -3268,8 +3264,7 @@ static int process_entry(struct merge_options *o,
                        clean_merge = 1;
                        if (handle_rename_via_dir(o,
                                                  conflict_info->pair1,
-                                                 conflict_info->branch1,
-                                                 conflict_info->branch2))
+                                                 conflict_info->branch1))
                                clean_merge = -1;
                        break;
                case RENAME_ADD:
@@ -3764,6 +3759,10 @@ int parse_merge_opt(struct merge_options *o, const char *s)
                        return -1;
                o->merge_detect_rename = 1;
        }
+       /*
+        * Please update $__git_merge_strategy_options in
+        * git-completion.bash when you add new options
+        */
        else
                return -1;
        return 0;
index e7cd337bee53cb02282a14c8aa88f2342edd2eb2..ce33b8906e5c589813c7d873c9173aa3aa2afddc 100644 (file)
@@ -119,8 +119,7 @@ static void prepare_in_pack_by_idx(struct packing_data *pdata)
  * this fall back code, just stay simple and fall back to using
  * in_pack[] array.
  */
-void oe_map_new_pack(struct packing_data *pack,
-                    struct packed_git *p)
+void oe_map_new_pack(struct packing_data *pack)
 {
        uint32_t i;
 
index 6bfacc7d2cedd7f399d7807b7746b6ed66737eed..6fde7ce27cbc15b33a3d994bad87ab140f3164a7 100644 (file)
@@ -247,14 +247,14 @@ static inline struct packed_git *oe_in_pack(const struct packing_data *pack,
                return pack->in_pack[e - pack->objects];
 }
 
-void oe_map_new_pack(struct packing_data *pack,
-                    struct packed_git *p);
+void oe_map_new_pack(struct packing_data *pack);
+
 static inline void oe_set_in_pack(struct packing_data *pack,
                                  struct object_entry *e,
                                  struct packed_git *p)
 {
        if (!p->index)
-               oe_map_new_pack(pack, p);
+               oe_map_new_pack(pack);
        if (pack->in_pack_by_idx)
                e->in_pack_idx = p->index;
        else
index 7d83e2971d9afa11b11d6187bd96afb88cbb6118..74cce4e7fce74237292e0b34bec2b02e0e945ca7 100644 (file)
@@ -222,6 +222,17 @@ const char *optname(const struct option *opt, int flags);
                BUG("option callback does not expect an argument"); \
 } while (0)
 
+/*
+ * Similar to the assertions above, but checks that "arg" is always non-NULL.
+ * This assertion also implies BUG_ON_OPT_NEG(), letting you declare both
+ * assertions in a single line.
+ */
+#define BUG_ON_OPT_NEG_NOARG(unset, arg) do { \
+       BUG_ON_OPT_NEG(unset); \
+       if(!(arg)) \
+               BUG("option callback expects an argument"); \
+} while(0)
+
 /*----- incremental advanced APIs -----*/
 
 enum parse_opt_result {
diff --git a/path.c b/path.c
index 03ab712839a7878e3d3b5d79c698f4e2bb29c8b1..25e97b8c3f76ce9246d8d985adba9777acd5f43c 100644 (file)
--- a/path.c
+++ b/path.c
@@ -115,10 +115,13 @@ static struct common_dir common_list[] = {
        { 1, 1, 0, "logs" },
        { 1, 1, 1, "logs/HEAD" },
        { 0, 1, 1, "logs/refs/bisect" },
+       { 0, 1, 1, "logs/refs/rewritten" },
+       { 0, 1, 1, "logs/refs/worktree" },
        { 0, 1, 0, "lost-found" },
        { 0, 1, 0, "objects" },
        { 0, 1, 0, "refs" },
        { 0, 1, 1, "refs/bisect" },
+       { 0, 1, 1, "refs/rewritten" },
        { 0, 1, 1, "refs/worktree" },
        { 0, 1, 0, "remotes" },
        { 0, 1, 0, "worktrees" },
index d4b71d3e82b0e54ef4105748fdfdc15b438badfb..ffd722054489e6ea837bb417578afd085cebb467 100644 (file)
@@ -88,13 +88,15 @@ static void packet_trace(const char *buf, unsigned int len, int write)
 void packet_flush(int fd)
 {
        packet_trace("0000", 4, 1);
-       write_or_die(fd, "0000", 4);
+       if (write_in_full(fd, "0000", 4) < 0)
+               die_errno(_("unable to write flush packet"));
 }
 
 void packet_delim(int fd)
 {
        packet_trace("0001", 4, 1);
-       write_or_die(fd, "0001", 4);
+       if (write_in_full(fd, "0001", 4) < 0)
+               die_errno(_("unable to write delim packet"));
 }
 
 int packet_flush_gently(int fd)
@@ -117,7 +119,7 @@ void packet_buf_delim(struct strbuf *buf)
        strbuf_add(buf, "0001", 4);
 }
 
-static void set_packet_header(char *buf, const int size)
+void set_packet_header(char *buf, const int size)
 {
        static char hexchar[] = "0123456789abcdef";
 
index ad9a4a2cd7c332cb1c4d1f26268f1ef45f2d7639..c36cb788ed47f388e9c51fca46cb6ec4e73830ef 100644 (file)
@@ -25,6 +25,7 @@ void packet_delim(int fd);
 void packet_write_fmt(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
 void packet_buf_flush(struct strbuf *buf);
 void packet_buf_delim(struct strbuf *buf);
+void set_packet_header(char *buf, int size);
 void packet_write(int fd_out, const char *buf, size_t size);
 void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
 void packet_buf_write_len(struct strbuf *buf, const char *data, size_t len);
index d2995b13edf4c64965321882677f28847f47e21c..f496f0f1284db4ea7c6a20022311381bd9dc1b64 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -98,6 +98,10 @@ static void setup_commit_formats(void)
                { "fuller",     CMIT_FMT_FULLER,        0,      8 },
                { "full",       CMIT_FMT_FULL,          0,      8 },
                { "oneline",    CMIT_FMT_ONELINE,       1,      0 }
+               /*
+                * Please update $__git_log_pretty_formats in
+                * git-completion.bash when you add new formats.
+                */
        };
        commit_formats_len = ARRAY_SIZE(builtin_formats);
        builtin_formats_len = commit_formats_len;
index 5e636785d14f8ef5283561d4606fface080bf3c0..9741f057505d2041be1e8dbd49b444aaeab4bd82 100644 (file)
@@ -17,6 +17,10 @@ static enum protocol_version parse_protocol_version(const char *value)
 enum protocol_version get_protocol_version_config(void)
 {
        const char *value;
+       enum protocol_version retval = protocol_v0;
+       const char *git_test_k = "GIT_TEST_PROTOCOL_VERSION";
+       const char *git_test_v = getenv(git_test_k);
+
        if (!git_config_get_string_const("protocol.version", &value)) {
                enum protocol_version version = parse_protocol_version(value);
 
@@ -24,10 +28,19 @@ enum protocol_version get_protocol_version_config(void)
                        die("unknown value for config 'protocol.version': %s",
                            value);
 
-               return version;
+               retval = version;
+       }
+
+       if (git_test_v && *git_test_v) {
+               enum protocol_version env = parse_protocol_version(git_test_v);
+
+               if (env == protocol_unknown_version)
+                       die("unknown value for %s: %s", git_test_k, git_test_v);
+               if (retval < env)
+                       retval = env;
        }
 
-       return protocol_v0;
+       return retval;
 }
 
 enum protocol_version determine_protocol_version_server(void)
index 6e9b810d2a5e03dc613fe1e58938086f1ed9b684..0d00a91de4c848dff499edb7dbbfda45ffda05fb 100644 (file)
@@ -12,6 +12,7 @@
 #include "packfile.h"
 #include "worktree.h"
 #include "object-store.h"
+#include "pack-bitmap.h"
 
 struct connectivity_progress {
        struct progress *progress;
@@ -158,10 +159,44 @@ int add_unseen_recent_objects_to_traversal(struct rev_info *revs,
                                      FOR_EACH_OBJECT_LOCAL_ONLY);
 }
 
+static void *lookup_object_by_type(struct repository *r,
+                                  const struct object_id *oid,
+                                  enum object_type type)
+{
+       switch (type) {
+       case OBJ_COMMIT:
+               return lookup_commit(r, oid);
+       case OBJ_TREE:
+               return lookup_tree(r, oid);
+       case OBJ_TAG:
+               return lookup_tag(r, oid);
+       case OBJ_BLOB:
+               return lookup_blob(r, oid);
+       default:
+               die("BUG: unknown object type %d", type);
+       }
+}
+
+static int mark_object_seen(const struct object_id *oid,
+                            enum object_type type,
+                            int exclude,
+                            uint32_t name_hash,
+                            struct packed_git *found_pack,
+                            off_t found_offset)
+{
+       struct object *obj = lookup_object_by_type(the_repository, oid, type);
+       if (!obj)
+               die("unable to create object '%s'", oid_to_hex(oid));
+
+       obj->flags |= SEEN;
+       return 0;
+}
+
 void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
                            timestamp_t mark_recent, struct progress *progress)
 {
        struct connectivity_progress cp;
+       struct bitmap_index *bitmap_git;
 
        /*
         * Set up revision parsing, and mark us as being interested
@@ -188,6 +223,13 @@ void mark_reachable_objects(struct rev_info *revs, int mark_reflog,
        cp.progress = progress;
        cp.count = 0;
 
+       bitmap_git = prepare_bitmap_walk(revs);
+       if (bitmap_git) {
+               traverse_bitmap_commit_list(bitmap_git, mark_object_seen);
+               free_bitmap_index(bitmap_git);
+               return;
+       }
+
        /*
         * Set up the revision walk - this will move all commits
         * from the pending list to the commit walking list.
index 422a9c9ae3fd2cfd552ce48c5e68ce18919b1eb9..3aca105307863f5342699babfbea2ac3035fdacb 100644 (file)
@@ -485,6 +485,10 @@ static struct {
        { "if", SOURCE_NONE, FIELD_STR, if_atom_parser },
        { "then", SOURCE_NONE },
        { "else", SOURCE_NONE },
+       /*
+        * Please update $__git_ref_fieldlist in git-completion.bash
+        * when you add new atoms
+        */
 };
 
 #define REF_FORMATTING_STATE_INIT  { 0, NULL }
@@ -913,7 +917,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_
 }
 
 /* See grab_values */
-static void grab_tag_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_tag_values(struct atom_value *val, int deref, struct object *obj)
 {
        int i;
        struct tag *tag = (struct tag *) obj;
@@ -935,7 +939,7 @@ static void grab_tag_values(struct atom_value *val, int deref, struct object *ob
 }
 
 /* See grab_values */
-static void grab_commit_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_commit_values(struct atom_value *val, int deref, struct object *obj)
 {
        int i;
        struct commit *commit = (struct commit *) obj;
@@ -968,7 +972,7 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object
        }
 }
 
-static const char *find_wholine(const char *who, int wholen, const char *buf, unsigned long sz)
+static const char *find_wholine(const char *who, int wholen, const char *buf)
 {
        const char *eol;
        while (*buf) {
@@ -1064,7 +1068,7 @@ static void grab_date(const char *buf, struct atom_value *v, const char *atomnam
 }
 
 /* See grab_values */
-static void grab_person(const char *who, struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_person(const char *who, struct atom_value *val, int deref, void *buf)
 {
        int i;
        int wholen = strlen(who);
@@ -1085,7 +1089,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
                    !starts_with(name + wholen, "date"))
                        continue;
                if (!wholine)
-                       wholine = find_wholine(who, wholen, buf, sz);
+                       wholine = find_wholine(who, wholen, buf);
                if (!wholine)
                        return; /* no point looking for it */
                if (name[wholen] == 0)
@@ -1105,7 +1109,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
        if (strcmp(who, "tagger") && strcmp(who, "committer"))
                return; /* "author" for commit object is not wanted */
        if (!wholine)
-               wholine = find_wholine(who, wholen, buf, sz);
+               wholine = find_wholine(who, wholen, buf);
        if (!wholine)
                return;
        for (i = 0; i < used_atom_cnt; i++) {
@@ -1123,7 +1127,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, stru
        }
 }
 
-static void find_subpos(const char *buf, unsigned long sz,
+static void find_subpos(const char *buf,
                        const char **sub, unsigned long *sublen,
                        const char **body, unsigned long *bodylen,
                        unsigned long *nonsiglen,
@@ -1192,7 +1196,7 @@ static void append_lines(struct strbuf *out, const char *buf, unsigned long size
 }
 
 /* See grab_values */
-static void grab_sub_body_contents(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf)
 {
        int i;
        const char *subpos = NULL, *bodypos = NULL, *sigpos = NULL;
@@ -1212,7 +1216,7 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, struct obj
                    !starts_with(name, "contents"))
                        continue;
                if (!subpos)
-                       find_subpos(buf, sz,
+                       find_subpos(buf,
                                    &subpos, &sublen,
                                    &bodypos, &bodylen, &nonsiglen,
                                    &sigpos, &siglen);
@@ -1265,19 +1269,19 @@ static void fill_missing_values(struct atom_value *val)
  * pointed at by the ref itself; otherwise it is the object the
  * ref (which is a tag) refers to.
  */
-static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf, unsigned long sz)
+static void grab_values(struct atom_value *val, int deref, struct object *obj, void *buf)
 {
        switch (obj->type) {
        case OBJ_TAG:
-               grab_tag_values(val, deref, obj, buf, sz);
-               grab_sub_body_contents(val, deref, obj, buf, sz);
-               grab_person("tagger", val, deref, obj, buf, sz);
+               grab_tag_values(val, deref, obj);
+               grab_sub_body_contents(val, deref, buf);
+               grab_person("tagger", val, deref, buf);
                break;
        case OBJ_COMMIT:
-               grab_commit_values(val, deref, obj, buf, sz);
-               grab_sub_body_contents(val, deref, obj, buf, sz);
-               grab_person("author", val, deref, obj, buf, sz);
-               grab_person("committer", val, deref, obj, buf, sz);
+               grab_commit_values(val, deref, obj);
+               grab_sub_body_contents(val, deref, buf);
+               grab_person("author", val, deref, buf);
+               grab_person("committer", val, deref, buf);
                break;
        case OBJ_TREE:
                /* grab_tree_values(val, deref, obj, buf, sz); */
@@ -1516,7 +1520,7 @@ static int get_object(struct ref_array_item *ref, int deref, struct object **obj
                        return strbuf_addf_ret(err, -1, _("parse_object_buffer failed on %s for %s"),
                                               oid_to_hex(&oi->oid), ref->refname);
                }
-               grab_values(ref->value, deref, *obj, oi->content, oi->size);
+               grab_values(ref->value, deref, *obj, oi->content);
        }
 
        grab_common_values(ref->value, deref, oi);
index dd8abe918508027ed46c3234bac1d91107c6ca94..5848f32ef8f206f489416cd3cfe52d12cc54ad36 100644 (file)
@@ -214,6 +214,33 @@ static void files_ref_path(struct files_ref_store *refs,
        }
 }
 
+/*
+ * Manually add refs/bisect, refs/rewritten and refs/worktree, which, being
+ * per-worktree, might not appear in the directory listing for
+ * refs/ in the main repo.
+ */
+static void add_per_worktree_entries_to_dir(struct ref_dir *dir, const char *dirname)
+{
+       const char *prefixes[] = { "refs/bisect/", "refs/worktree/", "refs/rewritten/" };
+       int ip;
+
+       if (strcmp(dirname, "refs/"))
+               return;
+
+       for (ip = 0; ip < ARRAY_SIZE(prefixes); ip++) {
+               const char *prefix = prefixes[ip];
+               int prefix_len = strlen(prefix);
+               struct ref_entry *child_entry;
+               int pos;
+
+               pos = search_ref_dir(dir, prefix, prefix_len);
+               if (pos >= 0)
+                       continue;
+               child_entry = create_dir_entry(dir->cache, prefix, prefix_len, 1);
+               add_entry_to_dir(dir, child_entry);
+       }
+}
+
 /*
  * Read the loose references from the namespace dirname into dir
  * (without recursing).  dirname must end with '/'.  dir must be the
@@ -297,28 +324,7 @@ static void loose_fill_ref_dir(struct ref_store *ref_store,
        strbuf_release(&path);
        closedir(d);
 
-       /*
-        * Manually add refs/bisect and refs/worktree, which, being
-        * per-worktree, might not appear in the directory listing for
-        * refs/ in the main repo.
-        */
-       if (!strcmp(dirname, "refs/")) {
-               int pos = search_ref_dir(dir, "refs/bisect/", 12);
-
-               if (pos < 0) {
-                       struct ref_entry *child_entry = create_dir_entry(
-                                       dir->cache, "refs/bisect/", 12, 1);
-                       add_entry_to_dir(dir, child_entry);
-               }
-
-               pos = search_ref_dir(dir, "refs/worktree/", 11);
-
-               if (pos < 0) {
-                       struct ref_entry *child_entry = create_dir_entry(
-                                       dir->cache, "refs/worktree/", 11, 1);
-                       add_entry_to_dir(dir, child_entry);
-               }
-       }
+       add_per_worktree_entries_to_dir(dir, dirname);
 }
 
 static struct ref_cache *get_loose_ref_cache(struct files_ref_store *refs)
@@ -2254,8 +2260,7 @@ static int split_head_update(struct ref_update *update,
  * Note that the new update will itself be subject to splitting when
  * the iteration gets to it.
  */
-static int split_symref_update(struct files_ref_store *refs,
-                              struct ref_update *update,
+static int split_symref_update(struct ref_update *update,
                               const char *referent,
                               struct ref_transaction *transaction,
                               struct string_list *affected_refnames,
@@ -2449,7 +2454,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
                         * of processing the split-off update, so we
                         * don't have to do it here.
                         */
-                       ret = split_symref_update(refs, update,
+                       ret = split_symref_update(update,
                                                  referent.buf, transaction,
                                                  affected_refnames, err);
                        if (ret)
index aad02dcc74b61d0701f1dd599339430df90f8465..8bba57270b00b72c7e70fe749880a29c1ddfea1f 100644 (file)
@@ -16,6 +16,7 @@
 #include "send-pack.h"
 #include "protocol.h"
 #include "quote.h"
+#include "transport.h"
 
 static struct remote *remote;
 /* always ends with a trailing slash */
@@ -153,7 +154,7 @@ static int set_option(const char *name, const char *value)
                else {
                        struct strbuf unquoted = STRBUF_INIT;
                        if (unquote_c_style(&unquoted, value, NULL) < 0)
-                               die("invalid quoting in push-option value");
+                               die(_("invalid quoting in push-option value: '%s'"), value);
                        string_list_append_nodup(&options.push_options,
                                                 strbuf_detach(&unquoted, NULL));
                }
@@ -250,8 +251,8 @@ static struct ref *parse_info_refs(struct discovery *heads)
                        mid = &data[i];
                if (data[i] == '\n') {
                        if (mid - start != 40)
-                               die("%sinfo/refs not valid: is this a git repository?",
-                                   url.buf);
+                               die(_("%sinfo/refs not valid: is this a git repository?"),
+                                   transport_anonymize_url(url.buf));
                        data[i] = 0;
                        ref_name = mid + 1;
                        ref = alloc_ref(ref_name);
@@ -351,7 +352,7 @@ static void check_smart_http(struct discovery *d, const char *service,
                           PACKET_READ_CHOMP_NEWLINE |
                           PACKET_READ_DIE_ON_ERR_PACKET);
        if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
-               die("invalid server response; expected service, got flush packet");
+               die(_("invalid server response; expected service, got flush packet"));
 
        if (skip_prefix(reader.line, "# service=", &p) && !strcmp(p, service)) {
                /*
@@ -382,7 +383,7 @@ static void check_smart_http(struct discovery *d, const char *service,
                d->proto_git = 1;
 
        } else {
-               die("invalid server response; got '%s'", reader.line);
+               die(_("invalid server response; got '%s'"), reader.line);
        }
 }
 
@@ -442,17 +443,23 @@ static struct discovery *discover_refs(const char *service, int for_push)
                break;
        case HTTP_MISSING_TARGET:
                show_http_message(&type, &charset, &buffer);
-               die("repository '%s' not found", url.buf);
+               die(_("repository '%s' not found"),
+                   transport_anonymize_url(url.buf));
        case HTTP_NOAUTH:
                show_http_message(&type, &charset, &buffer);
-               die("Authentication failed for '%s'", url.buf);
+               die(_("Authentication failed for '%s'"),
+                   transport_anonymize_url(url.buf));
        default:
                show_http_message(&type, &charset, &buffer);
-               die("unable to access '%s': %s", url.buf, curl_errorstr);
+               die(_("unable to access '%s': %s"),
+                   transport_anonymize_url(url.buf), curl_errorstr);
        }
 
-       if (options.verbosity && !starts_with(refs_url.buf, url.buf))
-               warning(_("redirecting to %s"), url.buf);
+       if (options.verbosity && !starts_with(refs_url.buf, url.buf)) {
+               char *u = transport_anonymize_url(url.buf);
+               warning(_("redirecting to %s"), u);
+               free(u);
+       }
 
        last= xcalloc(1, sizeof(*last_discovery));
        last->service = xstrdup(service);
@@ -505,8 +512,6 @@ static void output_refs(struct ref *refs)
 
 struct rpc_state {
        const char *service_name;
-       const char **argv;
-       struct strbuf *stdin_preamble;
        char *service_url;
        char *hdr_content_type;
        char *hdr_accept;
@@ -518,25 +523,121 @@ struct rpc_state {
        int in;
        int out;
        int any_written;
-       struct strbuf result;
        unsigned gzip_request : 1;
        unsigned initial_buffer : 1;
+
+       /*
+        * Whenever a pkt-line is read into buf, append the 4 characters
+        * denoting its length before appending the payload.
+        */
+       unsigned write_line_lengths : 1;
+
+       /*
+        * Used by rpc_out; initialize to 0. This is true if a flush has been
+        * read, but the corresponding line length (if write_line_lengths is
+        * true) and EOF have not been sent to libcurl. Since each flush marks
+        * the end of a request, each flush must be completely sent before any
+        * further reading occurs.
+        */
+       unsigned flush_read_but_not_sent : 1;
 };
 
+/*
+ * Appends the result of reading from rpc->out to the string represented by
+ * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
+ * enough space, 0 otherwise.
+ *
+ * If rpc->write_line_lengths is true, appends the line length as a 4-byte
+ * hexadecimal string before appending the result described above.
+ *
+ * Writes the total number of bytes appended into appended.
+ */
+static int rpc_read_from_out(struct rpc_state *rpc, int options,
+                            size_t *appended,
+                            enum packet_read_status *status) {
+       size_t left;
+       char *buf;
+       int pktlen_raw;
+
+       if (rpc->write_line_lengths) {
+               left = rpc->alloc - rpc->len - 4;
+               buf = rpc->buf + rpc->len + 4;
+       } else {
+               left = rpc->alloc - rpc->len;
+               buf = rpc->buf + rpc->len;
+       }
+
+       if (left < LARGE_PACKET_MAX)
+               return 0;
+
+       *status = packet_read_with_status(rpc->out, NULL, NULL, buf,
+                       left, &pktlen_raw, options);
+       if (*status != PACKET_READ_EOF) {
+               *appended = pktlen_raw + (rpc->write_line_lengths ? 4 : 0);
+               rpc->len += *appended;
+       }
+
+       if (rpc->write_line_lengths) {
+               switch (*status) {
+               case PACKET_READ_EOF:
+                       if (!(options & PACKET_READ_GENTLE_ON_EOF))
+                               die(_("shouldn't have EOF when not gentle on EOF"));
+                       break;
+               case PACKET_READ_NORMAL:
+                       set_packet_header(buf - 4, *appended);
+                       break;
+               case PACKET_READ_DELIM:
+                       memcpy(buf - 4, "0001", 4);
+                       break;
+               case PACKET_READ_FLUSH:
+                       memcpy(buf - 4, "0000", 4);
+                       break;
+               }
+       }
+
+       return 1;
+}
+
 static size_t rpc_out(void *ptr, size_t eltsize,
                size_t nmemb, void *buffer_)
 {
        size_t max = eltsize * nmemb;
        struct rpc_state *rpc = buffer_;
        size_t avail = rpc->len - rpc->pos;
+       enum packet_read_status status;
 
        if (!avail) {
                rpc->initial_buffer = 0;
-               avail = packet_read(rpc->out, NULL, NULL, rpc->buf, rpc->alloc, 0);
-               if (!avail)
-                       return 0;
+               rpc->len = 0;
                rpc->pos = 0;
-               rpc->len = avail;
+               if (!rpc->flush_read_but_not_sent) {
+                       if (!rpc_read_from_out(rpc, 0, &avail, &status))
+                               BUG("The entire rpc->buf should be larger than LARGE_PACKET_MAX");
+                       if (status == PACKET_READ_FLUSH)
+                               rpc->flush_read_but_not_sent = 1;
+               }
+               /*
+                * If flush_read_but_not_sent is true, we have already read one
+                * full request but have not fully sent it + EOF, which is why
+                * we need to refrain from reading.
+                */
+       }
+       if (rpc->flush_read_but_not_sent) {
+               if (!avail) {
+                       /*
+                        * The line length either does not need to be sent at
+                        * all or has already been completely sent. Now we can
+                        * return 0, indicating EOF, meaning that the flush has
+                        * been fully sent.
+                        */
+                       rpc->flush_read_but_not_sent = 0;
+                       return 0;
+               }
+               /*
+                * If avail is non-zerp, the line length for the flush still
+                * hasn't been fully sent. Proceed with sending the line
+                * length.
+                */
        }
 
        if (max < avail)
@@ -560,7 +661,7 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
                        rpc->pos = 0;
                        return CURLIOE_OK;
                }
-               error("unable to rewind rpc post data - try increasing http.postBuffer");
+               error(_("unable to rewind rpc post data - try increasing http.postBuffer"));
                return CURLIOE_FAILRESTART;
 
        default:
@@ -620,7 +721,7 @@ static int run_slot(struct active_request_slot *slot,
                                strbuf_addstr(&msg, curl_errorstr);
                        }
                }
-               error("RPC failed; %s", msg.buf);
+               error(_("RPC failed; %s"), msg.buf);
                strbuf_release(&msg);
        }
 
@@ -660,11 +761,15 @@ static curl_off_t xcurl_off_t(size_t len)
 {
        uintmax_t size = len;
        if (size > maximum_signed_value_of_type(curl_off_t))
-               die("cannot handle pushes this big");
+               die(_("cannot handle pushes this big"));
        return (curl_off_t)size;
 }
 
-static int post_rpc(struct rpc_state *rpc)
+/*
+ * If flush_received is true, do not attempt to read any more; just use what's
+ * in rpc->buf.
+ */
+static int post_rpc(struct rpc_state *rpc, int flush_received)
 {
        struct active_request_slot *slot;
        struct curl_slist *headers = http_copy_default_headers();
@@ -679,21 +784,19 @@ static int post_rpc(struct rpc_state *rpc)
         * allocated buffer space we can use HTTP/1.0 and avoid the
         * chunked encoding mess.
         */
-       while (1) {
-               size_t left = rpc->alloc - rpc->len;
-               char *buf = rpc->buf + rpc->len;
-               int n;
-
-               if (left < LARGE_PACKET_MAX) {
-                       large_request = 1;
-                       use_gzip = 0;
-                       break;
+       if (!flush_received) {
+               while (1) {
+                       size_t n;
+                       enum packet_read_status status;
+
+                       if (!rpc_read_from_out(rpc, 0, &n, &status)) {
+                               large_request = 1;
+                               use_gzip = 0;
+                               break;
+                       }
+                       if (status == PACKET_READ_FLUSH)
+                               break;
                }
-
-               n = packet_read(rpc->out, NULL, NULL, buf, left, 0);
-               if (!n)
-                       break;
-               rpc->len += n;
        }
 
        if (large_request) {
@@ -773,11 +876,11 @@ static int post_rpc(struct rpc_state *rpc)
 
                ret = git_deflate(&stream, Z_FINISH);
                if (ret != Z_STREAM_END)
-                       die("cannot deflate request; zlib deflate error %d", ret);
+                       die(_("cannot deflate request; zlib deflate error %d"), ret);
 
                ret = git_deflate_end_gently(&stream);
                if (ret != Z_OK)
-                       die("cannot deflate request; zlib end error %d", ret);
+                       die(_("cannot deflate request; zlib end error %d"), ret);
 
                gzip_size = stream.total_out;
 
@@ -829,22 +932,22 @@ static int post_rpc(struct rpc_state *rpc)
        return err;
 }
 
-static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
+static int rpc_service(struct rpc_state *rpc, struct discovery *heads,
+                      const char **client_argv, const struct strbuf *preamble,
+                      struct strbuf *rpc_result)
 {
        const char *svc = rpc->service_name;
        struct strbuf buf = STRBUF_INIT;
-       struct strbuf *preamble = rpc->stdin_preamble;
        struct child_process client = CHILD_PROCESS_INIT;
        int err = 0;
 
        client.in = -1;
        client.out = -1;
        client.git_cmd = 1;
-       client.argv = rpc->argv;
+       client.argv = client_argv;
        if (start_command(&client))
                exit(1);
-       if (preamble)
-               write_or_die(client.in, preamble->buf, preamble->len);
+       write_or_die(client.in, preamble->buf, preamble->len);
        if (heads)
                write_or_die(client.in, heads->buf, heads->len);
 
@@ -852,7 +955,6 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
        rpc->buf = xmalloc(rpc->alloc);
        rpc->in = client.in;
        rpc->out = client.out;
-       strbuf_init(&rpc->result, 0);
 
        strbuf_addf(&buf, "%s%s", url.buf, svc);
        rpc->service_url = strbuf_detach(&buf, NULL);
@@ -874,13 +976,13 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
                        break;
                rpc->pos = 0;
                rpc->len = n;
-               err |= post_rpc(rpc);
+               err |= post_rpc(rpc, 0);
        }
 
        close(client.in);
        client.in = -1;
        if (!err) {
-               strbuf_read(&rpc->result, client.out, 0);
+               strbuf_read(rpc_result, client.out, 0);
        } else {
                char buf[4096];
                for (;;)
@@ -909,7 +1011,7 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
 
        ALLOC_ARRAY(targets, nr_heads);
        if (options.depth || options.deepen_since)
-               die("dumb http transport does not support shallow capabilities");
+               die(_("dumb http transport does not support shallow capabilities"));
        for (i = 0; i < nr_heads; i++)
                targets[i] = xstrdup(oid_to_hex(&to_fetch[i]->old_oid));
 
@@ -923,7 +1025,7 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
                free(targets[i]);
        free(targets);
 
-       return ret ? error("fetch failed.") : 0;
+       return ret ? error(_("fetch failed.")) : 0;
 }
 
 static int fetch_git(struct discovery *heads,
@@ -933,6 +1035,7 @@ static int fetch_git(struct discovery *heads,
        struct strbuf preamble = STRBUF_INIT;
        int i, err;
        struct argv_array args = ARGV_ARRAY_INIT;
+       struct strbuf rpc_result = STRBUF_INIT;
 
        argv_array_pushl(&args, "fetch-pack", "--stateless-rpc",
                         "--stdin", "--lock-pack", NULL);
@@ -970,7 +1073,7 @@ static int fetch_git(struct discovery *heads,
        for (i = 0; i < nr_heads; i++) {
                struct ref *ref = to_fetch[i];
                if (!*ref->name)
-                       die("cannot fetch by sha1 over smart http");
+                       die(_("cannot fetch by sha1 over smart http"));
                packet_buf_write(&preamble, "%s %s\n",
                                 oid_to_hex(&ref->old_oid), ref->name);
        }
@@ -978,14 +1081,12 @@ static int fetch_git(struct discovery *heads,
 
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-upload-pack",
-       rpc.argv = args.argv;
-       rpc.stdin_preamble = &preamble;
        rpc.gzip_request = 1;
 
-       err = rpc_service(&rpc, heads);
-       if (rpc.result.len)
-               write_or_die(1, rpc.result.buf, rpc.result.len);
-       strbuf_release(&rpc.result);
+       err = rpc_service(&rpc, heads, args.argv, &preamble, &rpc_result);
+       if (rpc_result.len)
+               write_or_die(1, rpc_result.buf, rpc_result.len);
+       strbuf_release(&rpc_result);
        strbuf_release(&preamble);
        argv_array_clear(&args);
        return err;
@@ -1015,13 +1116,13 @@ static void parse_fetch(struct strbuf *buf)
                        struct object_id old_oid;
 
                        if (get_oid_hex(p, &old_oid))
-                               die("protocol error: expected sha/ref, got %s'", p);
+                               die(_("protocol error: expected sha/ref, got %s'"), p);
                        if (p[GIT_SHA1_HEXSZ] == ' ')
                                name = p + GIT_SHA1_HEXSZ + 1;
                        else if (!p[GIT_SHA1_HEXSZ])
                                name = "";
                        else
-                               die("protocol error: expected sha/ref, got %s'", p);
+                               die(_("protocol error: expected sha/ref, got %s'"), p);
 
                        ref = alloc_ref(name);
                        oidcpy(&ref->old_oid, &old_oid);
@@ -1033,7 +1134,7 @@ static void parse_fetch(struct strbuf *buf)
                        to_fetch[nr_heads++] = ref;
                }
                else
-                       die("http transport does not support %s", buf->buf);
+                       die(_("http transport does not support %s"), buf->buf);
 
                strbuf_reset(buf);
                if (strbuf_getline_lf(buf, stdin) == EOF)
@@ -1069,7 +1170,7 @@ static int push_dav(int nr_spec, char **specs)
                argv_array_push(&child.args, specs[i]);
 
        if (run_command(&child))
-               die("git-http-push failed");
+               die(_("git-http-push failed"));
        return 0;
 }
 
@@ -1080,6 +1181,7 @@ static int push_git(struct discovery *heads, int nr_spec, char **specs)
        struct argv_array args;
        struct string_list_item *cas_option;
        struct strbuf preamble = STRBUF_INIT;
+       struct strbuf rpc_result = STRBUF_INIT;
 
        argv_array_init(&args);
        argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
@@ -1112,13 +1214,11 @@ static int push_git(struct discovery *heads, int nr_spec, char **specs)
 
        memset(&rpc, 0, sizeof(rpc));
        rpc.service_name = "git-receive-pack",
-       rpc.argv = args.argv;
-       rpc.stdin_preamble = &preamble;
 
-       err = rpc_service(&rpc, heads);
-       if (rpc.result.len)
-               write_or_die(1, rpc.result.buf, rpc.result.len);
-       strbuf_release(&rpc.result);
+       err = rpc_service(&rpc, heads, args.argv, &preamble, &rpc_result);
+       if (rpc_result.len)
+               write_or_die(1, rpc_result.buf, rpc_result.len);
+       strbuf_release(&rpc_result);
        strbuf_release(&preamble);
        argv_array_clear(&args);
        return err;
@@ -1148,7 +1248,7 @@ static void parse_push(struct strbuf *buf)
                        specs[nr_spec++] = xstrdup(buf->buf + 5);
                }
                else
-                       die("http transport does not support %s", buf->buf);
+                       die(_("http transport does not support %s"), buf->buf);
 
                strbuf_reset(buf);
                if (strbuf_getline_lf(buf, stdin) == EOF)
@@ -1170,165 +1270,11 @@ static void parse_push(struct strbuf *buf)
        free(specs);
 }
 
-/*
- * Used to represent the state of a connection to an HTTP server when
- * communicating using git's wire-protocol version 2.
- */
-struct proxy_state {
-       char *service_name;
-       char *service_url;
-       struct curl_slist *headers;
-       struct strbuf request_buffer;
-       int in;
-       int out;
-       struct packet_reader reader;
-       size_t pos;
-       int seen_flush;
-};
-
-static void proxy_state_init(struct proxy_state *p, const char *service_name,
-                            enum protocol_version version)
-{
-       struct strbuf buf = STRBUF_INIT;
-
-       memset(p, 0, sizeof(*p));
-       p->service_name = xstrdup(service_name);
-
-       p->in = 0;
-       p->out = 1;
-       strbuf_init(&p->request_buffer, 0);
-
-       strbuf_addf(&buf, "%s%s", url.buf, p->service_name);
-       p->service_url = strbuf_detach(&buf, NULL);
-
-       p->headers = http_copy_default_headers();
-
-       strbuf_addf(&buf, "Content-Type: application/x-%s-request", p->service_name);
-       p->headers = curl_slist_append(p->headers, buf.buf);
-       strbuf_reset(&buf);
-
-       strbuf_addf(&buf, "Accept: application/x-%s-result", p->service_name);
-       p->headers = curl_slist_append(p->headers, buf.buf);
-       strbuf_reset(&buf);
-
-       p->headers = curl_slist_append(p->headers, "Transfer-Encoding: chunked");
-
-       /* Add the Git-Protocol header */
-       if (get_protocol_http_header(version, &buf))
-               p->headers = curl_slist_append(p->headers, buf.buf);
-
-       packet_reader_init(&p->reader, p->in, NULL, 0,
-                          PACKET_READ_GENTLE_ON_EOF |
-                          PACKET_READ_DIE_ON_ERR_PACKET);
-
-       strbuf_release(&buf);
-}
-
-static void proxy_state_clear(struct proxy_state *p)
-{
-       free(p->service_name);
-       free(p->service_url);
-       curl_slist_free_all(p->headers);
-       strbuf_release(&p->request_buffer);
-}
-
-/*
- * CURLOPT_READFUNCTION callback function.
- * Attempts to copy over a single packet-line at a time into the
- * curl provided buffer.
- */
-static size_t proxy_in(char *buffer, size_t eltsize,
-                      size_t nmemb, void *userdata)
-{
-       size_t max;
-       struct proxy_state *p = userdata;
-       size_t avail = p->request_buffer.len - p->pos;
-
-
-       if (eltsize != 1)
-               BUG("curl read callback called with size = %"PRIuMAX" != 1",
-                   (uintmax_t)eltsize);
-       max = nmemb;
-
-       if (!avail) {
-               if (p->seen_flush) {
-                       p->seen_flush = 0;
-                       return 0;
-               }
-
-               strbuf_reset(&p->request_buffer);
-               switch (packet_reader_read(&p->reader)) {
-               case PACKET_READ_EOF:
-                       die("unexpected EOF when reading from parent process");
-               case PACKET_READ_NORMAL:
-                       packet_buf_write_len(&p->request_buffer, p->reader.line,
-                                            p->reader.pktlen);
-                       break;
-               case PACKET_READ_DELIM:
-                       packet_buf_delim(&p->request_buffer);
-                       break;
-               case PACKET_READ_FLUSH:
-                       packet_buf_flush(&p->request_buffer);
-                       p->seen_flush = 1;
-                       break;
-               }
-               p->pos = 0;
-               avail = p->request_buffer.len;
-       }
-
-       if (max < avail)
-               avail = max;
-       memcpy(buffer, p->request_buffer.buf + p->pos, avail);
-       p->pos += avail;
-       return avail;
-}
-
-static size_t proxy_out(char *buffer, size_t eltsize,
-                       size_t nmemb, void *userdata)
-{
-       size_t size;
-       struct proxy_state *p = userdata;
-
-       if (eltsize != 1)
-               BUG("curl read callback called with size = %"PRIuMAX" != 1",
-                   (uintmax_t)eltsize);
-       size = nmemb;
-
-       write_or_die(p->out, buffer, size);
-       return size;
-}
-
-/* Issues a request to the HTTP server configured in `p` */
-static int proxy_request(struct proxy_state *p)
-{
-       struct active_request_slot *slot;
-
-       slot = get_active_slot();
-
-       curl_easy_setopt(slot->curl, CURLOPT_ENCODING, "");
-       curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
-       curl_easy_setopt(slot->curl, CURLOPT_POST, 1);
-       curl_easy_setopt(slot->curl, CURLOPT_URL, p->service_url);
-       curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, p->headers);
-
-       /* Setup function to read request from client */
-       curl_easy_setopt(slot->curl, CURLOPT_READFUNCTION, proxy_in);
-       curl_easy_setopt(slot->curl, CURLOPT_READDATA, p);
-
-       /* Setup function to write server response to client */
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, proxy_out);
-       curl_easy_setopt(slot->curl, CURLOPT_WRITEDATA, p);
-
-       if (run_slot(slot, NULL) != HTTP_OK)
-               return -1;
-
-       return 0;
-}
-
 static int stateless_connect(const char *service_name)
 {
        struct discovery *discover;
-       struct proxy_state p;
+       struct rpc_state rpc;
+       struct strbuf buf = STRBUF_INIT;
 
        /*
         * Run the info/refs request and see if the server supports protocol
@@ -1348,23 +1294,58 @@ static int stateless_connect(const char *service_name)
                fflush(stdout);
        }
 
-       proxy_state_init(&p, service_name, discover->version);
+       rpc.service_name = service_name;
+       rpc.service_url = xstrfmt("%s%s", url.buf, rpc.service_name);
+       rpc.hdr_content_type = xstrfmt("Content-Type: application/x-%s-request", rpc.service_name);
+       rpc.hdr_accept = xstrfmt("Accept: application/x-%s-result", rpc.service_name);
+       if (get_protocol_http_header(discover->version, &buf)) {
+               rpc.protocol_header = strbuf_detach(&buf, NULL);
+       } else {
+               rpc.protocol_header = NULL;
+               strbuf_release(&buf);
+       }
+       rpc.buf = xmalloc(http_post_buffer);
+       rpc.alloc = http_post_buffer;
+       rpc.len = 0;
+       rpc.pos = 0;
+       rpc.in = 1;
+       rpc.out = 0;
+       rpc.any_written = 0;
+       rpc.gzip_request = 1;
+       rpc.initial_buffer = 0;
+       rpc.write_line_lengths = 1;
+       rpc.flush_read_but_not_sent = 0;
 
        /*
         * Dump the capability listing that we got from the server earlier
         * during the info/refs request.
         */
-       write_or_die(p.out, discover->buf, discover->len);
+       write_or_die(rpc.in, discover->buf, discover->len);
+
+       /* Until we see EOF keep sending POSTs */
+       while (1) {
+               size_t avail;
+               enum packet_read_status status;
 
-       /* Peek the next packet line.  Until we see EOF keep sending POSTs */
-       while (packet_reader_peek(&p.reader) != PACKET_READ_EOF) {
-               if (proxy_request(&p)) {
+               if (!rpc_read_from_out(&rpc, PACKET_READ_GENTLE_ON_EOF, &avail,
+                                      &status))
+                       BUG("The entire rpc->buf should be larger than LARGE_PACKET_MAX");
+               if (status == PACKET_READ_EOF)
+                       break;
+               if (post_rpc(&rpc, status == PACKET_READ_FLUSH))
                        /* We would have an err here */
                        break;
-               }
+               /* Reset the buffer for next request */
+               rpc.len = 0;
        }
 
-       proxy_state_clear(&p);
+       free(rpc.service_url);
+       free(rpc.hdr_content_type);
+       free(rpc.hdr_accept);
+       free(rpc.protocol_header);
+       free(rpc.buf);
+       strbuf_release(&buf);
+
        return 0;
 }
 
@@ -1375,7 +1356,7 @@ int cmd_main(int argc, const char **argv)
 
        setup_git_directory_gently(&nongit);
        if (argc < 2) {
-               error("remote-curl: usage: git remote-curl <remote> [<url>]");
+               error(_("remote-curl: usage: git remote-curl <remote> [<url>]"));
                return 1;
        }
 
@@ -1407,14 +1388,14 @@ int cmd_main(int argc, const char **argv)
 
                if (strbuf_getline_lf(&buf, stdin) == EOF) {
                        if (ferror(stdin))
-                               error("remote-curl: error reading command stream from git");
+                               error(_("remote-curl: error reading command stream from git"));
                        return 1;
                }
                if (buf.len == 0)
                        break;
                if (starts_with(buf.buf, "fetch ")) {
                        if (nongit)
-                               die("remote-curl: fetch attempted without a local repo");
+                               die(_("remote-curl: fetch attempted without a local repo"));
                        parse_fetch(&buf);
 
                } else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
@@ -1454,7 +1435,7 @@ int cmd_main(int argc, const char **argv)
                        if (!stateless_connect(arg))
                                break;
                } else {
-                       error("remote-curl: unknown command '%s' from git", buf.buf);
+                       error(_("remote-curl: unknown command '%s' from git"), buf.buf);
                        return 1;
                }
                strbuf_reset(&buf);
index 5cad2dcc86a530ab088cda98a5c64bbe78102038..682c239fe3eda6c16b7be45fc5c920a325d61817 100644 (file)
@@ -157,7 +157,7 @@ int repo_init(struct repository *repo,
              const char *gitdir,
              const char *worktree)
 {
-       struct repository_format format;
+       struct repository_format format = REPOSITORY_FORMAT_INIT;
        memset(repo, 0, sizeof(*repo));
 
        repo->objects = raw_object_store_new();
@@ -174,6 +174,7 @@ int repo_init(struct repository *repo,
        if (worktree)
                repo_set_worktree(repo, worktree);
 
+       clear_repository_format(&format);
        return 0;
 
 error:
index eb8e51bc6302b65dfc5a921d59b2bcacd6cc19d9..cb69a227d5cb9cb58c0173fac666e1ee384ba6ef 100644 (file)
@@ -2689,6 +2689,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
        if (revs->first_parent_only && revs->bisect)
                die(_("--first-parent is incompatible with --bisect"));
 
+       if (revs->line_level_traverse &&
+           (revs->diffopt.output_format & ~(DIFF_FORMAT_PATCH | DIFF_FORMAT_NO_OUTPUT)))
+               die(_("-L does not yet support diff formats besides -p and -s"));
+
        if (revs->expand_tabs_in_log < 0)
                revs->expand_tabs_in_log = revs->expand_tabs_in_log_default;
 
index 95dda23eee450d1d60a70434d254071c6c05146b..79a046d748300d76ec66f5fd4cd0cb0e681b5651 100644 (file)
@@ -2137,7 +2137,8 @@ static int parse_insn_line(struct repository *r, struct todo_item *item,
        item->arg_len = (int)(eol - item->arg);
 
        if (status < 0)
-               return -1;
+               return error(_("could not parse '%.*s'"),
+                            (int)(end_of_object_name - bol), bol);
 
        item->commit = lookup_commit_reference(r, &commit_oid);
        return !item->commit;
@@ -3640,7 +3641,6 @@ static int pick_commits(struct repository *r,
                        res = do_exec(r, item->arg);
                        *end_of_arg = saved;
 
-                       /* Reread the todo file if it has changed. */
                        if (res) {
                                if (opts->reschedule_failed_exec)
                                        reschedule = 1;
@@ -3648,6 +3648,7 @@ static int pick_commits(struct repository *r,
                                res = error_errno(_("could not stat '%s'"),
                                                  get_todo_path(opts));
                        else if (match_stat_data(&todo_list->stat, &st)) {
+                               /* Reread the todo file if it has changed. */
                                todo_list_release(todo_list);
                                if (read_populate_todo(r, todo_list, opts))
                                        res = -1; /* message was printed */
diff --git a/setup.c b/setup.c
index ca9e8a949ed869183f16c57520f19fb361100a02..d0c958c3b2a4a7d4b53970b0e623ed8f6e6a4be4 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -411,6 +411,7 @@ static int read_worktree_config(const char *var, const char *value, void *vdata)
        } else if (strcmp(var, "core.worktree") == 0) {
                if (!value)
                        return config_error_nonbool(var);
+               free(data->work_tree);
                data->work_tree = xstrdup(value);
        }
        return 0;
@@ -476,7 +477,7 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
        }
 
        repository_format_precious_objects = candidate->precious_objects;
-       repository_format_partial_clone = candidate->partial_clone;
+       repository_format_partial_clone = xstrdup_or_null(candidate->partial_clone);
        repository_format_worktree_config = candidate->worktree_config;
        string_list_clear(&candidate->unknown_extensions, 0);
 
@@ -499,27 +500,38 @@ static int check_repository_format_gently(const char *gitdir, struct repository_
                }
                if (candidate->work_tree) {
                        free(git_work_tree_cfg);
-                       git_work_tree_cfg = candidate->work_tree;
+                       git_work_tree_cfg = xstrdup(candidate->work_tree);
                        inside_work_tree = -1;
                }
-       } else {
-               free(candidate->work_tree);
        }
 
        return 0;
 }
 
+static void init_repository_format(struct repository_format *format)
+{
+       const struct repository_format fresh = REPOSITORY_FORMAT_INIT;
+
+       memcpy(format, &fresh, sizeof(fresh));
+}
+
 int read_repository_format(struct repository_format *format, const char *path)
 {
-       memset(format, 0, sizeof(*format));
-       format->version = -1;
-       format->is_bare = -1;
-       format->hash_algo = GIT_HASH_SHA1;
-       string_list_init(&format->unknown_extensions, 1);
+       clear_repository_format(format);
        git_config_from_file(check_repo_format, path, format);
+       if (format->version == -1)
+               clear_repository_format(format);
        return format->version;
 }
 
+void clear_repository_format(struct repository_format *format)
+{
+       string_list_clear(&format->unknown_extensions, 0);
+       free(format->work_tree);
+       free(format->partial_clone);
+       init_repository_format(format);
+}
+
 int verify_repository_format(const struct repository_format *format,
                             struct strbuf *err)
 {
@@ -997,7 +1009,7 @@ int discover_git_directory(struct strbuf *commondir,
        struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
        size_t gitdir_offset = gitdir->len, cwd_len;
        size_t commondir_offset = commondir->len;
-       struct repository_format candidate;
+       struct repository_format candidate = REPOSITORY_FORMAT_INIT;
 
        if (strbuf_getcwd(&dir))
                return -1;
@@ -1034,9 +1046,11 @@ int discover_git_directory(struct strbuf *commondir,
                strbuf_release(&err);
                strbuf_setlen(commondir, commondir_offset);
                strbuf_setlen(gitdir, gitdir_offset);
+               clear_repository_format(&candidate);
                return -1;
        }
 
+       clear_repository_format(&candidate);
        return 0;
 }
 
@@ -1045,7 +1059,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
        static struct strbuf cwd = STRBUF_INIT;
        struct strbuf dir = STRBUF_INIT, gitdir = STRBUF_INIT;
        const char *prefix = NULL;
-       struct repository_format repo_fmt;
+       struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
 
        /*
         * We may have read an incomplete configuration before
@@ -1157,6 +1171,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
        strbuf_release(&dir);
        strbuf_release(&gitdir);
+       clear_repository_format(&repo_fmt);
 
        return prefix;
 }
@@ -1214,9 +1229,10 @@ int git_config_perm(const char *var, const char *value)
 
 void check_repository_format(void)
 {
-       struct repository_format repo_fmt;
+       struct repository_format repo_fmt = REPOSITORY_FORMAT_INIT;
        check_repository_format_gently(get_git_dir(), &repo_fmt, NULL);
        startup_info->have_repository = 1;
+       clear_repository_format(&repo_fmt);
 }
 
 /*
index 6dda2c16df1026e50b7d9be255b6bbfc4e92725c..cfe5c874b6f06361b444ec897fddcc36e19979f3 100644 (file)
@@ -442,6 +442,18 @@ static enum get_oid_result get_short_oid(const char *name, int len,
        find_short_packed_object(&ds);
        status = finish_object_disambiguation(&ds, oid);
 
+       /*
+        * If we didn't find it, do the usual reprepare() slow-path,
+        * since the object may have recently been added to the repository
+        * or migrated from loose to packed.
+        */
+       if (status == MISSING_OBJECT) {
+               reprepare_packed_git(the_repository);
+               find_short_object_filename(&ds);
+               find_short_packed_object(&ds);
+               status = finish_object_disambiguation(&ds, oid);
+       }
+
        if (!quietly && (status == SHORT_NAME_AMBIGUOUS)) {
                struct oid_array collect = OID_ARRAY_INIT;
 
index 232357eb2ea0397388254a4b188333a227bf5b10..16033998da4b273aebd92c84b1e1b12e4aaf7009 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 232357eb2ea0397388254a4b188333a227bf5b10
+Subproject commit 16033998da4b273aebd92c84b1e1b12e4aaf7009
index df0630bc6d607749f80955bc9ffaa5b0bbc506a5..5931cf25d518ac3bfc30c3b2adb8ddfc0ccbf187 100644 (file)
 #endif
 /*ENDIANNESS SELECTION*/
 
+#ifndef SHA1DC_FORCE_ALIGNED_ACCESS
 #if defined(SHA1DC_FORCE_UNALIGNED_ACCESS) || defined(SHA1DC_ON_INTEL_LIKE_PROCESSOR)
 #define SHA1DC_ALLOW_UNALIGNED_ACCESS
-#endif /*UNALIGNMENT DETECTION*/
-
+#endif /*UNALIGNED ACCESS DETECTION*/
+#endif /*FORCE ALIGNED ACCESS*/
 
 #define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n))))
 #define rotate_left(x,n)  (((x)<<(n))|((x)>>(32-(n))))
index 52702c62d9e3a205c14bdd9f468509f98fe4ced1..66653e86b9f87de01332e3d1405edd218cbf1581 100644 (file)
@@ -281,7 +281,10 @@ static int parse_fetch_recurse(const char *opt, const char *arg,
        default:
                if (!strcmp(arg, "on-demand"))
                        return RECURSE_SUBMODULES_ON_DEMAND;
-
+               /*
+                * Please update $__git_fetch_recurse_submodules in
+                * git-completion.bash when you add new options.
+                */
                if (die_on_error)
                        die("bad %s argument: %s", opt, arg);
                else
@@ -362,6 +365,10 @@ static int parse_push_recurse(const char *opt, const char *arg,
                        return RECURSE_SUBMODULES_CHECK;
                else if (!strcmp(arg, "only"))
                        return RECURSE_SUBMODULES_ONLY;
+               /*
+                * Please update $__git_push_recurse_submodules in
+                * git-completion.bash when you add new modes.
+                */
                else if (die_on_error)
                        die("bad %s argument: %s", opt, arg);
                else
index 174003a847aa9a8c6de666fc24ece9213ccb0921..b16c0ecc950c177e9f6bd0c553d593b08855a478 100644 (file)
@@ -432,6 +432,10 @@ void handle_ignore_submodules_arg(struct diff_options *diffopt,
                diffopt->flags.ignore_dirty_submodules = 1;
        else if (strcmp(arg, "none"))
                die("bad --ignore-submodules argument: %s", arg);
+       /*
+        * Please update _git_status() in git-completion.bash when you
+        * add new options
+        */
 }
 
 static int prepare_submodule_summary(struct rev_info *rev, const char *path,
@@ -1544,6 +1548,13 @@ static int fetch_finish(int retvalue, struct strbuf *err,
        struct oid_array *commits;
 
        if (retvalue)
+               /*
+                * NEEDSWORK: This indicates that the overall fetch
+                * failed, even though there may be a subsequent fetch
+                * by commit hash that might work. It may be a good
+                * idea to not indicate failure in this case, and only
+                * indicate failure if the subsequent fetch fails.
+                */
                spf->result = 1;
 
        if (!task || !task->sub)
index 7a3d582267c7f8f70f018d95dbed4d085ed89f98..da721d3314c386db3278965958ce90c8441db2ff 100644 (file)
--- a/t/README
+++ b/t/README
@@ -196,11 +196,10 @@ appropriately before running "make".
        variable to "1" or "0", respectively.
 
 --stress::
---stress=<N>::
        Run the test script repeatedly in multiple parallel jobs until
        one of them fails.  Useful for reproducing rare failures in
        flaky tests.  The number of parallel jobs is, in order of
-       precedence: <N>, or the value of the GIT_TEST_STRESS_LOAD
+       precedence: the value of the GIT_TEST_STRESS_LOAD
        environment variable, or twice the number of available
        processors (as shown by the 'getconf' utility), or 8.
        Implies `--verbose -x --immediate` to get the most information
@@ -211,10 +210,13 @@ appropriately before running "make".
        '.stress-<nr>' suffix, and the trash directory of the failed
        test job is renamed to end with a '.stress-failed' suffix.
 
+--stress-jobs=<N>::
+       Override the number of parallel jobs. Implies `--stress`.
+
 --stress-limit=<N>::
        When combined with --stress run the test script repeatedly
        this many times in each of the parallel jobs or until one of
-       them fails, whichever comes first.
+       them fails, whichever comes first. Implies `--stress`.
 
 You can also set the GIT_TEST_INSTALLED environment variable to
 the bindir of an existing git installation to test that installation.
@@ -341,6 +343,9 @@ marked strings" in po/README for details.
 GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole
 test suite. Accept any boolean values that are accepted by git-config.
 
+GIT_TEST_PROTOCOL_VERSION=<n>, when set, overrides the
+'protocol.version' setting to n if it is less than n.
+
 GIT_TEST_FULL_IN_PACK_ARRAY=<boolean> exercises the uncommon
 pack-objects code path where there are more than 1024 packs even if
 the actual number of packs in repository is below this limit. Accept
@@ -379,10 +384,6 @@ the --no-sparse command-line argument.
 GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path
 by overriding the minimum number of cache entries required per thread.
 
-GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the
-builtin version of git-rebase. See 'rebase.useBuiltin' in
-git-config(1).
-
 GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading
 of the index for the whole test suite by bypassing the default number of
 cache entries and thread minimums. Setting this to 1 will make the
diff --git a/t/perf/p5304-prune.sh b/t/perf/p5304-prune.sh
new file mode 100755 (executable)
index 0000000..83baedb
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+test_description='performance tests of prune'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'remove reachable loose objects' '
+       git repack -ad
+'
+
+test_expect_success 'remove unreachable loose objects' '
+       git prune
+'
+
+test_expect_success 'confirm there are no loose objects' '
+       git count-objects | grep ^0
+'
+
+test_perf 'prune with no objects' '
+       git prune
+'
+
+test_expect_success 'repack with bitmaps' '
+       git repack -adb
+'
+
+# We have to create the object in each trial run, since otherwise
+# runs after the first see no object and just skip the traversal entirely!
+test_perf 'prune with bitmaps' '
+       echo "probably not present in repo" | git hash-object -w --stdin &&
+       git prune
+'
+
+test_done
index 2e33ab3ec3ef9838962c7a8b1a997faeed11f071..169f92eae3d419b2d9d4ccdfbde4a394cc9e15dd 100644 (file)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see http://www.gnu.org/licenses/ .
 
-# do the --tee work early; it otherwise confuses our careful
-# GIT_BUILD_DIR mangling
-case "$GIT_TEST_TEE_STARTED, $* " in
-done,*)
-       # do not redirect again
-       ;;
-*' --tee '*|*' --va'*)
-       mkdir -p test-results
-       BASE=test-results/$(basename "$0" .sh)
-       (GIT_TEST_TEE_STARTED=done ${SHELL-sh} "$0" "$@" 2>&1;
-        echo $? > $BASE.exit) | tee $BASE.out
-       test "$(cat $BASE.exit)" = 0
-       exit
-       ;;
-esac
-
+# These variables must be set before the inclusion of test-lib.sh below,
+# because it will change our working directory.
 TEST_DIRECTORY=$(pwd)/..
 TEST_OUTPUT_DIRECTORY=$(pwd)
-if test -z "$GIT_TEST_INSTALLED"; then
-       perf_results_prefix=
-else
-       perf_results_prefix=$(printf "%s" "${GIT_TEST_INSTALLED%/bin-wrappers}" | tr -c "[a-zA-Z0-9]" "[_*]")"."
-       # make the tested dir absolute
-       GIT_TEST_INSTALLED=$(cd "$GIT_TEST_INSTALLED" && pwd)
-fi
+ABSOLUTE_GIT_TEST_INSTALLED=$(
+       test -n "$GIT_TEST_INSTALLED" && cd "$GIT_TEST_INSTALLED" && pwd)
 
 TEST_NO_CREATE_REPO=t
 TEST_NO_MALLOC_CHECK=t
 
 . ../test-lib.sh
 
+if test -z "$GIT_TEST_INSTALLED"; then
+       perf_results_prefix=
+else
+       perf_results_prefix=$(printf "%s" "${GIT_TEST_INSTALLED%/bin-wrappers}" | tr -c "[a-zA-Z0-9]" "[_*]")"."
+       GIT_TEST_INSTALLED=$ABSOLUTE_GIT_TEST_INSTALLED
+fi
+
 # Variables from test-lib that are normally internal to the tests; we
 # need to export them for test_perf subshells
 export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP
index 5e27604b24a7357575c1d51c7cafda9f5cb06471..1f462204eaf878694be8045313097155480cec57 100755 (executable)
@@ -454,6 +454,17 @@ test_expect_success 're-init from a linked worktree' '
        )
 '
 
+test_expect_success MINGW 'core.hidedotfiles = false' '
+       git config --global core.hidedotfiles false &&
+       rm -rf newdir &&
+       mkdir newdir &&
+       (
+               sane_unset GIT_DIR GIT_WORK_TREE GIT_CONFIG &&
+               git -C newdir init
+       ) &&
+       ! is_hidden newdir/.git
+'
+
 test_expect_success MINGW 'redirect std handles' '
        GIT_REDIRECT_STDOUT=output.txt git rev-parse --git-dir &&
        test .git = "$(cat output.txt)" &&
index 4feb65157d87e803a6cd2caf6cec2a945f54b085..bc89371f53436dbf3427f231f560ef1b1f8683f6 100755 (executable)
@@ -127,4 +127,14 @@ test_expect_success 'fetch into corrupted repo with index-pack' '
        )
 '
 
+test_expect_success 'internal tree objects are not "missing"' '
+       git init missing-empty &&
+       (
+               cd missing-empty &&
+               empty_tree=$(git hash-object -t tree /dev/null) &&
+               commit=$(echo foo | git commit-tree $empty_tree) &&
+               git rev-list --objects $commit
+       )
+'
+
 test_done
index b664e51250ae0fcd6b1520a2fa424f34aa6d0479..bb2c7572a3849821f0f6b26f83c1130bb572e04b 100755 (executable)
@@ -76,4 +76,39 @@ test_expect_success 'reflog of worktrees/xx/HEAD' '
        test_cmp expected actual.wt2
 '
 
+test_expect_success 'for-each-ref from main repo' '
+       mkdir fer1 &&
+       git -C fer1 init repo &&
+       test_commit -C fer1/repo initial &&
+       git -C fer1/repo worktree add ../second &&
+       git -C fer1/repo update-ref refs/bisect/main HEAD &&
+       git -C fer1/repo update-ref refs/rewritten/main HEAD &&
+       git -C fer1/repo update-ref refs/worktree/main HEAD &&
+       git -C fer1/repo for-each-ref --format="%(refname)" | grep main >actual &&
+       cat >expected <<-\EOF &&
+       refs/bisect/main
+       refs/rewritten/main
+       refs/worktree/main
+       EOF
+       test_cmp expected actual
+'
+
+test_expect_success 'for-each-ref from linked repo' '
+       mkdir fer2 &&
+       git -C fer2 init repo &&
+       test_commit -C fer2/repo initial &&
+       git -C fer2/repo worktree add ../second &&
+       git -C fer2/second update-ref refs/bisect/second HEAD &&
+       git -C fer2/second update-ref refs/rewritten/second HEAD &&
+       git -C fer2/second update-ref refs/worktree/second HEAD &&
+       git -C fer2/second for-each-ref --format="%(refname)" | grep second >actual &&
+       cat >expected <<-\EOF &&
+       refs/bisect/second
+       refs/heads/second
+       refs/rewritten/second
+       refs/worktree/second
+       EOF
+       test_cmp expected actual
+'
+
 test_done
index c61f97214137f5fcf5a9d6b7dd98ea8162e9916d..49f08d5b9c078412af8ee6343519094521c86c24 100755 (executable)
@@ -740,7 +740,7 @@ test_expect_success 'fsck detects truncated loose object' '
 # for each of type, we have one version which is referenced by another object
 # (and so while unreachable, not dangling), and another variant which really is
 # dangling.
-test_expect_success 'fsck notices dangling objects' '
+test_expect_success 'create dangling-object repository' '
        git init dangling &&
        (
                cd dangling &&
@@ -751,12 +751,17 @@ test_expect_success 'fsck notices dangling objects' '
                commit=$(git commit-tree $tree) &&
                dcommit=$(git commit-tree -p $commit $tree) &&
 
-               cat >expect <<-EOF &&
+               cat >expect <<-EOF
                dangling blob $dblob
                dangling commit $dcommit
                dangling tree $dtree
                EOF
+       )
+'
 
+test_expect_success 'fsck notices dangling objects' '
+       (
+               cd dangling &&
                git fsck >actual &&
                # the output order is non-deterministic, as it comes from a hash
                sort <actual >actual.sorted &&
@@ -764,6 +769,16 @@ test_expect_success 'fsck notices dangling objects' '
        )
 '
 
+test_expect_success 'fsck --connectivity-only notices dangling objects' '
+       (
+               cd dangling &&
+               git fsck --connectivity-only >actual &&
+               # the output order is non-deterministic, as it comes from a hash
+               sort <actual >actual.sorted &&
+               test_i18ncmp expect actual.sorted
+       )
+'
+
 test_expect_success 'fsck $name notices bogus $name' '
        test_must_fail git fsck bogus &&
        test_must_fail git fsck $ZERO_OID
index 7e189851348d571b2e654325ba38e7564d0bc950..fca3f858245781229ea29b4baeb86e356f50a571 100755 (executable)
@@ -46,4 +46,28 @@ test_expect_success '-m restores 3-way conflicted+resolved file' '
        test_cmp both.txt.conflicted.cleaned both.txt.cleaned
 '
 
+test_expect_success 'force checkout a conflict file creates stage zero entry' '
+       git init co-force &&
+       (
+               cd co-force &&
+               echo a >a &&
+               git add a &&
+               git commit -ama &&
+               A_OBJ=$(git rev-parse :a) &&
+               git branch topic &&
+               echo b >a &&
+               git commit -amb &&
+               B_OBJ=$(git rev-parse :a) &&
+               git checkout topic &&
+               echo c >a &&
+               C_OBJ=$(git hash-object a) &&
+               git checkout -m master &&
+               test_cmp_rev :1:a $A_OBJ &&
+               test_cmp_rev :2:a $B_OBJ &&
+               test_cmp_rev :3:a $C_OBJ &&
+               git checkout -f topic &&
+               test_cmp_rev :0:a $A_OBJ
+       )
+'
+
 test_done
index 3e73f7584ce7d3a23e7e75d0f71bd595f5f822a3..42f147858d7c2e87d6920cdd77744e99bf77001b 100755 (executable)
@@ -59,6 +59,14 @@ test_expect_success 'rebase against master' '
        git rebase master
 '
 
+test_expect_success 'rebase sets ORIG_HEAD to pre-rebase state' '
+       git checkout -b orig-head topic &&
+       pre="$(git rev-parse --verify HEAD)" &&
+       git rebase master &&
+       test_cmp_rev "$pre" ORIG_HEAD &&
+       ! test_cmp_rev "$pre" HEAD
+'
+
 test_expect_success 'rebase, with <onto> and <upstream> specified as :/quuxery' '
        test_when_finished "git branch -D torebase" &&
        git checkout -b torebase my-topic-branch^ &&
@@ -311,4 +319,20 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '
        )
 '
 
+test_expect_success 'rebase -c rebase.useBuiltin=false warning' '
+       expected="rebase.useBuiltin support has been removed" &&
+
+       # Only warn when the legacy rebase is requested...
+       test_must_fail git -c rebase.useBuiltin=false rebase 2>err &&
+       test_i18ngrep "$expected" err &&
+       test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&
+       test_i18ngrep "$expected" err &&
+
+       # ...not when we would have used the built-in anyway
+       test_must_fail git -c rebase.useBuiltin=true rebase 2>err &&
+       test_must_be_empty err &&
+       test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&
+       test_must_be_empty err
+'
+
 test_done
index b60b11f9f2f820bb7347a845eb66524528c668f9..1723e1a858585d9e83d7662326a6f337db7e1fa6 100755 (executable)
@@ -149,12 +149,10 @@ test_expect_success 'rebase -i with the exec command checks tree cleanness' '
 
 test_expect_success 'rebase -x with empty command fails' '
        test_when_finished "git rebase --abort ||:" &&
-       test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \
-               git rebase -x "" @ 2>actual &&
+       test_must_fail env git rebase -x "" @ 2>actual &&
        test_write_lines "error: empty exec command" >expected &&
        test_i18ncmp expected actual &&
-       test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \
-               git rebase -x " " @ 2>actual &&
+       test_must_fail env git rebase -x " " @ 2>actual &&
        test_i18ncmp expected actual
 '
 
@@ -162,8 +160,7 @@ LF='
 '
 test_expect_success 'rebase -x with newline in command fails' '
        test_when_finished "git rebase --abort ||:" &&
-       test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true \
-               git rebase -x "a${LF}b" @ 2>actual &&
+       test_must_fail env git rebase -x "a${LF}b" @ 2>actual &&
        test_write_lines "error: exec commands cannot contain newlines" \
                         >expected &&
        test_i18ncmp expected actual
index b9292dfc2a329b32472368fb2874cc4a1e14cf47..76f6d306eaf39e9727bfeb3dbb04aa3c3941cf1d 100755 (executable)
@@ -11,4 +11,26 @@ test_expect_success 'rebase exec modifies rebase-todo' '
        test -e F
 '
 
+test_expect_success SHA1 'loose object cache vs re-reading todo list' '
+       GIT_REBASE_TODO=.git/rebase-merge/git-rebase-todo &&
+       export GIT_REBASE_TODO &&
+       write_script append-todo.sh <<-\EOS &&
+       # For values 5 and 6, this yields SHA-1s with the same first two digits
+       echo "pick $(git rev-parse --short \
+               $(printf "%s\\n" \
+                       "tree $EMPTY_TREE" \
+                       "author A U Thor <author@example.org> $1 +0000" \
+                       "committer A U Thor <author@example.org> $1 +0000" \
+                       "" \
+                       "$1" |
+                 git hash-object -t commit -w --stdin))" >>$GIT_REBASE_TODO
+
+       shift
+       test -z "$*" ||
+       echo "exec $0 $*" >>$GIT_REBASE_TODO
+       EOS
+
+       git rebase HEAD -x "./append-todo.sh 5 6"
+'
+
 test_done
index 04e5d42bd3b82a7bf683659f6fdd8e20813df770..85ae7dc1e4618275413a8b498f43d43f3e0ead92 100755 (executable)
@@ -8,91 +8,92 @@ test_description='Test of the various options to git rm.'
 . ./test-lib.sh
 
 # Setup some files to be removed, some with funny characters
-test_expect_success \
-    'Initialize test directory' \
-    "touch -- foo bar baz 'space embedded' -q &&
-     git add -- foo bar baz 'space embedded' -q &&
-     git commit -m 'add normal files'"
+test_expect_success 'Initialize test directory' '
+       touch -- foo bar baz "space embedded" -q &&
+       git add -- foo bar baz "space embedded" -q &&
+       git commit -m "add normal files"
+'
 
-if test_have_prereq !FUNNYNAMES; then
+if test_have_prereq !FUNNYNAMES
+then
        say 'Your filesystem does not allow tabs in filenames.'
 fi
 
-test_expect_success FUNNYNAMES 'add files with funny names' "
-     touch -- 'tab     embedded' 'newline
-embedded' &&
-     git add -- 'tab   embedded' 'newline
-embedded' &&
-     git commit -m 'add files with tabs and newlines'
-"
-
-test_expect_success \
-    'Pre-check that foo exists and is in index before git rm foo' \
-    '[ -f foo ] && git ls-files --error-unmatch foo'
-
-test_expect_success \
-    'Test that git rm foo succeeds' \
-    'git rm --cached foo'
-
-test_expect_success \
-    'Test that git rm --cached foo succeeds if the index matches the file' \
-    'echo content >foo &&
-     git add foo &&
-     git rm --cached foo'
-
-test_expect_success \
-    'Test that git rm --cached foo succeeds if the index matches the file' \
-    'echo content >foo &&
-     git add foo &&
-     git commit -m foo &&
-     echo "other content" >foo &&
-     git rm --cached foo'
-
-test_expect_success \
-    'Test that git rm --cached foo fails if the index matches neither the file nor HEAD' '
-     echo content >foo &&
-     git add foo &&
-     git commit -m foo --allow-empty &&
-     echo "other content" >foo &&
-     git add foo &&
-     echo "yet another content" >foo &&
-     test_must_fail git rm --cached foo
-'
-
-test_expect_success \
-    'Test that git rm --cached -f foo works in case where --cached only did not' \
-    'echo content >foo &&
-     git add foo &&
-     git commit -m foo --allow-empty &&
-     echo "other content" >foo &&
-     git add foo &&
-     echo "yet another content" >foo &&
-     git rm --cached -f foo'
-
-test_expect_success \
-    'Post-check that foo exists but is not in index after git rm foo' \
-    '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo'
-
-test_expect_success \
-    'Pre-check that bar exists and is in index before "git rm bar"' \
-    '[ -f bar ] && git ls-files --error-unmatch bar'
-
-test_expect_success \
-    'Test that "git rm bar" succeeds' \
-    'git rm bar'
-
-test_expect_success \
-    'Post-check that bar does not exist and is not in index after "git rm -f bar"' \
-    '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar'
-
-test_expect_success \
-    'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \
-    'git rm -- -q'
-
-test_expect_success FUNNYNAMES \
-    "Test that \"git rm -f\" succeeds with embedded space, tab, or newline characters." \
-    "git rm -f 'space embedded' 'tab   embedded' 'newline
-embedded'"
+test_expect_success FUNNYNAMES 'add files with funny names' '
+       touch -- "tab   embedded" "newline${LF}embedded" &&
+       git add -- "tab embedded" "newline${LF}embedded" &&
+       git commit -m "add files with tabs and newlines"
+'
+
+test_expect_success 'Pre-check that foo exists and is in index before git rm foo' '
+       test_path_is_file foo &&
+       git ls-files --error-unmatch foo
+'
+
+test_expect_success 'Test that git rm foo succeeds' '
+       git rm --cached foo
+'
+
+test_expect_success 'Test that git rm --cached foo succeeds if the index matches the file' '
+       echo content >foo &&
+       git add foo &&
+       git rm --cached foo
+'
+
+test_expect_success 'Test that git rm --cached foo succeeds if the index matches the file' '
+       echo content >foo &&
+       git add foo &&
+       git commit -m foo &&
+       echo "other content" >foo &&
+       git rm --cached foo
+'
+
+test_expect_success 'Test that git rm --cached foo fails if the index matches neither the file nor HEAD' '
+       echo content >foo &&
+       git add foo &&
+       git commit -m foo --allow-empty &&
+       echo "other content" >foo &&
+       git add foo &&
+       echo "yet another content" >foo &&
+       test_must_fail git rm --cached foo
+'
+
+test_expect_success 'Test that git rm --cached -f foo works in case where --cached only did not' '
+       echo content >foo &&
+       git add foo &&
+       git commit -m foo --allow-empty &&
+       echo "other content" >foo &&
+       git add foo &&
+       echo "yet another content" >foo &&
+       git rm --cached -f foo
+'
+
+test_expect_success 'Post-check that foo exists but is not in index after git rm foo' '
+       test_path_is_file foo &&
+       test_must_fail git ls-files --error-unmatch foo
+'
+
+test_expect_success 'Pre-check that bar exists and is in index before "git rm bar"' '
+       test_path_is_file bar &&
+       git ls-files --error-unmatch bar
+'
+
+test_expect_success 'Test that "git rm bar" succeeds' '
+       git rm bar
+'
+
+test_expect_success 'Post-check that bar does not exist and is not in index after "git rm -f bar"' '
+       test_path_is_missing bar &&
+       test_must_fail git ls-files --error-unmatch bar
+'
+
+test_expect_success 'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' '
+       git rm -- -q
+'
+
+test_expect_success FUNNYNAMES 'Test that "git rm -f" succeeds with embedded space, tab, or newline characters.' '
+       git rm -f "space embedded" "tab embedded" "newline${LF}embedded"
+'
 
 test_expect_success SANITY 'Test that "git rm -f" fails if its rm fails' '
        test_when_finished "chmod 775 ." &&
@@ -100,9 +101,9 @@ test_expect_success SANITY 'Test that "git rm -f" fails if its rm fails' '
        test_must_fail git rm -f baz
 '
 
-test_expect_success \
-    'When the rm in "git rm -f" fails, it should not remove the file from the index' \
-    'git ls-files --error-unmatch baz'
+test_expect_success 'When the rm in "git rm -f" fails, it should not remove the file from the index' '
+       git ls-files --error-unmatch baz
+'
 
 test_expect_success 'Remove nonexistent file with --ignore-unmatch' '
        git rm --ignore-unmatch nonexistent
@@ -137,15 +138,15 @@ test_expect_success 'Re-add foo and baz' '
 test_expect_success 'Modify foo -- rm should refuse' '
        echo >>foo &&
        test_must_fail git rm foo baz &&
-       test -f foo &&
-       test -f baz &&
+       test_path_is_file foo &&
+       test_path_is_file baz &&
        git ls-files --error-unmatch foo baz
 '
 
 test_expect_success 'Modified foo -- rm -f should work' '
        git rm -f foo baz &&
-       test ! -f foo &&
-       test ! -f baz &&
+       test_path_is_missing foo &&
+       test_path_is_missing baz &&
        test_must_fail git ls-files --error-unmatch foo &&
        test_must_fail git ls-files --error-unmatch bar
 '
@@ -159,15 +160,15 @@ test_expect_success 'Re-add foo and baz for HEAD tests' '
 
 test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
        test_must_fail git rm foo baz &&
-       test -f foo &&
-       test -f baz &&
+       test_path_is_file foo &&
+       test_path_is_file baz &&
        git ls-files --error-unmatch foo baz
 '
 
 test_expect_success 'but with -f it should work.' '
        git rm -f foo baz &&
-       test ! -f foo &&
-       test ! -f baz &&
+       test_path_is_missing foo &&
+       test_path_is_missing baz &&
        test_must_fail git ls-files --error-unmatch foo &&
        test_must_fail git ls-files --error-unmatch baz
 '
@@ -194,21 +195,21 @@ test_expect_success 'Recursive test setup' '
 
 test_expect_success 'Recursive without -r fails' '
        test_must_fail git rm frotz &&
-       test -d frotz &&
-       test -f frotz/nitfol
+       test_path_is_dir frotz &&
+       test_path_is_file frotz/nitfol
 '
 
 test_expect_success 'Recursive with -r but dirty' '
        echo qfwfq >>frotz/nitfol &&
        test_must_fail git rm -r frotz &&
-       test -d frotz &&
-       test -f frotz/nitfol
+       test_path_is_dir frotz &&
+       test_path_is_file frotz/nitfol
 '
 
 test_expect_success 'Recursive with -r -f' '
        git rm -f -r frotz &&
-       ! test -f frotz/nitfol &&
-       ! test -d frotz
+       test_path_is_missing frotz/nitfol &&
+       test_path_is_missing frotz
 '
 
 test_expect_success 'Remove nonexistent file returns nonzero exit status' '
@@ -217,23 +218,25 @@ test_expect_success 'Remove nonexistent file returns nonzero exit status' '
 
 test_expect_success 'Call "rm" from outside the work tree' '
        mkdir repo &&
-       (cd repo &&
-        git init &&
-        echo something >somefile &&
-        git add somefile &&
-        git commit -m "add a file" &&
-        (cd .. &&
-         git --git-dir=repo/.git --work-tree=repo rm somefile) &&
-       test_must_fail git ls-files --error-unmatch somefile)
+       (
+               cd repo &&
+               git init &&
+               echo something >somefile &&
+               git add somefile &&
+               git commit -m "add a file" &&
+               (
+                       cd .. &&
+                       git --git-dir=repo/.git --work-tree=repo rm somefile
+               ) &&
+               test_must_fail git ls-files --error-unmatch somefile
+       )
 '
 
 test_expect_success 'refresh index before checking if it is up-to-date' '
-
        git reset --hard &&
        test-tool chmtime -86400 frotz/nitfol &&
        git rm frotz/nitfol &&
-       test ! -f frotz/nitfol
-
+       test_path_is_missing frotz/nitfol
 '
 
 test_expect_success 'choking "git rm" should not let it die with cruft' '
@@ -242,8 +245,8 @@ test_expect_success 'choking "git rm" should not let it die with cruft' '
        i=0 &&
        while test $i -lt 12000
        do
-           echo "100644 1234567890123456789012345678901234567890 0     some-file-$i"
-           i=$(( $i + 1 ))
+               echo "100644 1234567890123456789012345678901234567890 0 some-file-$i"
+               i=$(( $i + 1 ))
        done | git update-index --index-info &&
        git rm -n "some-file-*" | : &&
        test_path_is_missing .git/index.lock
@@ -254,7 +257,7 @@ test_expect_success 'rm removes subdirectories recursively' '
        echo content >dir/subdir/subsubdir/file &&
        git add dir/subdir/subsubdir/file &&
        git rm -f dir/subdir/subsubdir/file &&
-       ! test -d dir
+       test_path_is_missing dir
 '
 
 cat >expect <<EOF
@@ -292,7 +295,7 @@ test_expect_success 'rm removes empty submodules from work tree' '
        git add .gitmodules &&
        git commit -m "add submodule" &&
        git rm submod &&
-       test ! -e submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual &&
        test_must_fail git config -f .gitmodules submodule.sub.url &&
@@ -314,7 +317,7 @@ test_expect_success 'rm removes work tree of unmodified submodules' '
        git reset --hard &&
        git submodule update &&
        git rm submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual &&
        test_must_fail git config -f .gitmodules submodule.sub.url &&
@@ -325,7 +328,7 @@ test_expect_success 'rm removes a submodule with a trailing /' '
        git reset --hard &&
        git submodule update &&
        git rm submod/ &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -343,12 +346,12 @@ test_expect_success 'rm of a populated submodule with different HEAD fails unles
        git submodule update &&
        git -C submod checkout HEAD^ &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.modified actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual &&
        test_must_fail git config -f .gitmodules submodule.sub.url &&
@@ -359,8 +362,8 @@ test_expect_success 'rm --cached leaves work tree of populated submodules and .g
        git reset --hard &&
        git submodule update &&
        git rm --cached submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno >actual &&
        test_cmp expect.cached actual &&
        git config -f .gitmodules submodule.sub.url &&
@@ -371,7 +374,7 @@ test_expect_success 'rm --dry-run does not touch the submodule or .gitmodules' '
        git reset --hard &&
        git submodule update &&
        git rm -n submod &&
-       test -f submod/.git &&
+       test_path_is_file submod/.git &&
        git diff-index --exit-code HEAD
 '
 
@@ -381,8 +384,8 @@ test_expect_success 'rm does not complain when no .gitmodules file is found' '
        git rm .gitmodules &&
        git rm submod >actual 2>actual.err &&
        test_must_be_empty actual.err &&
-       ! test -d submod &&
-       ! test -f submod/.git &&
+       test_path_is_missing submod &&
+       test_path_is_missing submod/.git &&
        git status -s -uno >actual &&
        test_cmp expect.both_deleted actual
 '
@@ -392,15 +395,15 @@ test_expect_success 'rm will error out on a modified .gitmodules file unless sta
        git submodule update &&
        git config -f .gitmodules foo.bar true &&
        test_must_fail git rm submod >actual 2>actual.err &&
-       test -s actual.err &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_file_not_empty actual.err &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git diff-files --quiet -- submod &&
        git add .gitmodules &&
        git rm submod >actual 2>actual.err &&
        test_must_be_empty actual.err &&
-       ! test -d submod &&
-       ! test -f submod/.git &&
+       test_path_is_missing submod &&
+       test_path_is_missing submod/.git &&
        git status -s -uno >actual &&
        test_cmp expect actual
 '
@@ -413,8 +416,8 @@ test_expect_success 'rm issues a warning when section is not found in .gitmodule
        echo "warning: Could not find section in .gitmodules where path=submod" >expect.err &&
        git rm submod >actual 2>actual.err &&
        test_i18ncmp expect.err actual.err &&
-       ! test -d submod &&
-       ! test -f submod/.git &&
+       test_path_is_missing submod &&
+       test_path_is_missing submod/.git &&
        git status -s -uno >actual &&
        test_cmp expect actual
 '
@@ -424,12 +427,12 @@ test_expect_success 'rm of a populated submodule with modifications fails unless
        git submodule update &&
        echo X >submod/empty &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.modified_inside actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -439,12 +442,12 @@ test_expect_success 'rm of a populated submodule with untracked files fails unle
        git submodule update &&
        echo X >submod/untracked &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.modified_untracked actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -481,7 +484,7 @@ test_expect_success 'rm removes work tree of unmodified conflicted submodule' '
        git submodule update &&
        test_must_fail git merge conflict2 &&
        git rm submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -493,12 +496,12 @@ test_expect_success 'rm of a conflicted populated submodule with different HEAD
        git -C submod checkout HEAD^ &&
        test_must_fail git merge conflict2 &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.conflict actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual &&
        test_must_fail git config -f .gitmodules submodule.sub.url &&
@@ -512,12 +515,12 @@ test_expect_success 'rm of a conflicted populated submodule with modifications f
        echo X >submod/empty &&
        test_must_fail git merge conflict2 &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.conflict actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual &&
        test_must_fail git config -f .gitmodules submodule.sub.url &&
@@ -531,12 +534,12 @@ test_expect_success 'rm of a conflicted populated submodule with untracked files
        echo X >submod/untracked &&
        test_must_fail git merge conflict2 &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.conflict actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -545,20 +548,21 @@ test_expect_success 'rm of a conflicted populated submodule with a .git director
        git checkout conflict1 &&
        git reset --hard &&
        git submodule update &&
-       (cd submod &&
+       (
+               cd submod &&
                rm .git &&
                cp -R ../.git/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        test_must_fail git merge conflict2 &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -d submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_dir submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.conflict actual &&
        test_must_fail git rm -f submod &&
-       test -d submod &&
-       test -d submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_dir submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.conflict actual &&
        git merge --abort &&
@@ -570,7 +574,7 @@ test_expect_success 'rm of a conflicted unpopulated submodule succeeds' '
        git reset --hard &&
        test_must_fail git merge conflict2 &&
        git rm submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -579,17 +583,18 @@ test_expect_success 'rm of a populated submodule with a .git directory migrates
        git checkout -f master &&
        git reset --hard &&
        git submodule update &&
-       (cd submod &&
+       (
+               cd submod &&
                rm .git &&
                cp -R ../.git/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree &&
                rm -r ../.git/modules/sub
        ) &&
        git rm submod 2>output.err &&
-       ! test -d submod &&
-       ! test -d submod/.git &&
+       test_path_is_missing submod &&
+       test_path_is_missing submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
-       test -s actual &&
+       test_file_not_empty actual &&
        test_i18ngrep Migrating output.err
 '
 
@@ -600,7 +605,8 @@ EOF
 test_expect_success 'setup subsubmodule' '
        git reset --hard &&
        git submodule update &&
-       (cd submod &&
+       (
+               cd submod &&
                git update-index --add --cacheinfo 160000 $(git rev-parse HEAD) subsubmod &&
                git config -f .gitmodules submodule.sub.url ../. &&
                git config -f .gitmodules submodule.sub.path subsubmod &&
@@ -614,7 +620,7 @@ test_expect_success 'setup subsubmodule' '
 
 test_expect_success 'rm recursively removes work tree of unmodified submodules' '
        git rm submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -624,12 +630,12 @@ test_expect_success 'rm of a populated nested submodule with different nested HE
        git submodule update --recursive &&
        git -C submod/subsubmod checkout HEAD^ &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.modified_inside actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -639,12 +645,12 @@ test_expect_success 'rm of a populated nested submodule with nested modification
        git submodule update --recursive &&
        echo X >submod/subsubmod/empty &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.modified_inside actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -654,12 +660,12 @@ test_expect_success 'rm of a populated nested submodule with nested untracked fi
        git submodule update --recursive &&
        echo X >submod/subsubmod/untracked &&
        test_must_fail git rm submod &&
-       test -d submod &&
-       test -f submod/.git &&
+       test_path_is_dir submod &&
+       test_path_is_file submod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect.modified_untracked actual &&
        git rm -f submod &&
-       test ! -d submod &&
+       test_path_is_missing submod &&
        git status -s -uno --ignore-submodules=none >actual &&
        test_cmp expect actual
 '
@@ -667,16 +673,17 @@ test_expect_success 'rm of a populated nested submodule with nested untracked fi
 test_expect_success "rm absorbs submodule's nested .git directory" '
        git reset --hard &&
        git submodule update --recursive &&
-       (cd submod/subsubmod &&
+       (
+               cd submod/subsubmod &&
                rm .git &&
                mv ../../.git/modules/sub/modules/sub .git &&
                GIT_WORK_TREE=. git config --unset core.worktree
        ) &&
        git rm submod 2>output.err &&
-       ! test -d submod &&
-       ! test -d submod/subsubmod/.git &&
+       test_path_is_missing submod &&
+       test_path_is_missing submod/subsubmod/.git &&
        git status -s -uno --ignore-submodules=none >actual &&
-       test -s actual &&
+       test_file_not_empty actual &&
        test_i18ngrep Migrating output.err
 '
 
index 909c743c134c5e18e0a80db3eae2dfb6e8210e6a..b6e2fdbc4410f1b8b04586f12bb8806e85a10e8d 100755 (executable)
@@ -589,6 +589,12 @@ test_expect_success 'excessive subject' '
        ls patches/0004-This-is-an-excessively-long-subject-line-for-a-messa.patch
 '
 
+test_expect_success 'failure to write cover-letter aborts gracefully' '
+       test_when_finished "rmdir 0000-cover-letter.patch" &&
+       mkdir 0000-cover-letter.patch &&
+       test_must_fail git format-patch --no-renames --cover-letter -1
+'
+
 test_expect_success 'cover-letter inherits diff options' '
        git mv file foo &&
        git commit -m foo &&
index 07b49f6d6d9ef93476af2af10fe694d2f971b59d..d4afe125548bed5e7e881d2bb4ae54f237968f28 100755 (executable)
@@ -480,18 +480,18 @@ test_expect_success FUNNYNAMES 'setup for --combined-all-paths with funny names'
        git branch side1d &&
        git branch side2d &&
        git checkout side1d &&
-       test_seq 1 10 >$(printf "file\twith\ttabs") &&
+       test_seq 1 10 >"$(printf "file\twith\ttabs")" &&
        git add file* &&
        git commit -m with &&
        git checkout side2d &&
-       test_seq 1 9 >$(printf "i\tam\ttabbed") &&
-       echo ten >>$(printf "i\tam\ttabbed") &&
+       test_seq 1 9 >"$(printf "i\tam\ttabbed")" &&
+       echo ten >>"$(printf "i\tam\ttabbed")" &&
        git add *tabbed &&
        git commit -m iam &&
        git checkout -b funny-names-mergery side1d &&
        git merge --no-commit side2d &&
        git rm *tabs &&
-       echo eleven >>$(printf "i\tam\ttabbed") &&
+       echo eleven >>"$(printf "i\tam\ttabbed")" &&
        git mv "$(printf "i\tam\ttabbed")" "$(printf "fickle\tnaming")" &&
        git add fickle* &&
        git commit
index 6e0dd6f9e5c482631147bb4770498dc4e7a8165f..4331b3118a07f900305fa783914091f73653bb45 100755 (executable)
@@ -137,4 +137,12 @@ test_expect_success 'diff --no-index from repo subdir with absolute paths' '
        test_cmp expect actual
 '
 
+test_expect_success 'diff --no-index allows external diff' '
+       test_expect_code 1 \
+               env GIT_EXTERNAL_DIFF="echo external ;:" \
+               git diff --no-index non/git/a non/git/b >actual &&
+       echo external >expect &&
+       test_cmp expect actual
+'
+
 test_done
index 55b577d919b5d82dd8c8bc81a6a4bc657b190f41..3f7f750cc8d7442458323f9ec77a371db3818320 100755 (executable)
@@ -77,14 +77,12 @@ test_expect_success 'setup: messages' '
 
        printf "Subject: " >subject-prefix &&
 
-       cat - subject-prefix msg-without-scissors-line >msg-with-scissors-line <<-\EOF &&
+       cat - subject-prefix msg-without-scissors-line >msg-with-scissors-line <<-\EOF
        This line should not be included in the commit message with --scissors enabled.
 
         - - >8 - - remove everything above this line - - >8 - -
 
        EOF
-
-       signoff="Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
 '
 
 test_expect_success setup '
index bd5fe4d1483005175d9c2211dee1901c2b132573..1db7bd0f59b46768d6559c37e026cde41821763a 100755 (executable)
@@ -115,4 +115,21 @@ test_expect_success 'range_set_union' '
        git log $(for x in $(test_seq 200); do echo -L $((2*x)),+1:c.c; done)
 '
 
+test_expect_success '-s shows only line-log commits' '
+       git log --format="commit %s" -L1,24:b.c >expect.raw &&
+       grep ^commit expect.raw >expect &&
+       git log --format="commit %s" -L1,24:b.c -s >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '-p shows the default patch output' '
+       git log -L1,24:b.c >expect &&
+       git log -L1,24:b.c -p >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success '--raw is forbidden' '
+       test_must_fail git log -L1,24:b.c --raw
+'
+
 test_done
index 270da21ac3e2931a42683392536500c4bb1fb5c3..1eeb828a15146e9e5040c64b20a31329853f12e7 100755 (executable)
@@ -118,10 +118,10 @@ test_expect_success 'prune: do not prune detached HEAD with no reflog' '
 
 test_expect_success 'prune: prune former HEAD after checking out branch' '
 
-       head_sha1=$(git rev-parse HEAD) &&
+       head_oid=$(git rev-parse HEAD) &&
        git checkout --quiet master &&
        git prune -v >prune_actual &&
-       grep "$head_sha1" prune_actual
+       grep "$head_oid" prune_actual
 
 '
 
@@ -265,15 +265,27 @@ EOF
 '
 
 test_expect_success 'prune .git/shallow' '
-       SHA1=$(echo hi|git commit-tree HEAD^{tree}) &&
-       echo $SHA1 >.git/shallow &&
+       oid=$(echo hi|git commit-tree HEAD^{tree}) &&
+       echo $oid >.git/shallow &&
        git prune --dry-run >out &&
-       grep $SHA1 .git/shallow &&
-       grep $SHA1 out &&
+       grep $oid .git/shallow &&
+       grep $oid out &&
        git prune &&
        test_path_is_missing .git/shallow
 '
 
+test_expect_success 'prune .git/shallow when there are no loose objects' '
+       oid=$(echo hi|git commit-tree HEAD^{tree}) &&
+       echo $oid >.git/shallow &&
+       git update-ref refs/heads/shallow-tip $oid &&
+       git repack -ad &&
+       # verify assumption that all loose objects are gone
+       git count-objects | grep ^0 &&
+       git prune &&
+       echo $oid >expect &&
+       test_cmp expect .git/shallow
+'
+
 test_expect_success 'prune: handle alternate object database' '
        test_create_repo A &&
        git -C A commit --allow-empty -m "initial commit" &&
@@ -314,8 +326,8 @@ test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
                git reset --hard HEAD^
        ) &&
        git prune --expire=now &&
-       SHA1=`git hash-object expected` &&
-       git -C third-worktree show "$SHA1" >actual &&
+       oid=`git hash-object expected` &&
+       git -C third-worktree show "$oid" >actual &&
        test_cmp expected actual
 '
 
index f1932ea431dca6d5aa2ad71575b7767413eeac18..571d620aedbac122960b319130ebad64a49d4f5b 100755 (executable)
@@ -288,7 +288,7 @@ test_expect_success 'receive-pack de-dupes .have lines' '
        $shared .have
        EOF
 
-       GIT_TRACE_PACKET=$(pwd)/trace \
+       GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION= \
            git push \
                --receive-pack="unset GIT_TRACE_PACKET; git-receive-pack" \
                fork HEAD:foo &&
index 49c540b1e1dbd5fc7d9a7baa36ee93a2ed3fc3c3..0ef4d6f20c226d544daa4ea62adf19e4ec946ce4 100755 (executable)
@@ -636,7 +636,9 @@ test_expect_success 'fetch-pack cannot fetch a raw sha1 that is not advertised a
        test_commit -C server 6 &&
 
        git init client &&
-       test_must_fail git -C client fetch-pack ../server \
+       # Some protocol versions (e.g. 2) support fetching
+       # unadvertised objects, so restrict this test to v0.
+       test_must_fail env GIT_TEST_PROTOCOL_VERSION= git -C client fetch-pack ../server \
                $(git -C server rev-parse refs/heads/master^) 2>err &&
        test_i18ngrep "Server does not allow request for unadvertised object" err
 '
index 4ca48f02761d4379bf5e01cb862e47830ec0c5ac..6041a4dd3278c7701f5e9dd46bfdab7ffbd0cc7a 100755 (executable)
@@ -47,7 +47,7 @@ get_needs () {
        test -s "$1" &&
        perl -alne '
                next unless $F[1] eq "upload-pack<";
-               last if $F[2] eq "0000";
+               next unless $F[2] eq "want";
                print $F[2], " ", $F[3];
        ' "$1"
 }
index ced15ae1224247355125fcbad7ad2184f9861cbe..e3c4a48c8536e46e0aa36b4d862b3876617335a4 100755 (executable)
@@ -223,7 +223,9 @@ test_expect_success 'ls-remote --symref' '
        $(git rev-parse refs/tags/mark1.10)     refs/tags/mark1.10
        $(git rev-parse refs/tags/mark1.2)      refs/tags/mark1.2
        EOF
-       git ls-remote --symref >actual &&
+       # Protocol v2 supports sending symrefs for refs other than HEAD, so use
+       # protocol v0 here.
+       GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref >actual &&
        test_cmp expect actual
 '
 
@@ -232,7 +234,9 @@ test_expect_success 'ls-remote with filtered symref (refname)' '
        ref: refs/heads/master  HEAD
        1bd44cb9d13204b0fe1958db0082f5028a16eb3a        HEAD
        EOF
-       git ls-remote --symref . HEAD >actual &&
+       # Protocol v2 supports sending symrefs for refs other than HEAD, so use
+       # protocol v0 here.
+       GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref . HEAD >actual &&
        test_cmp expect actual
 '
 
@@ -243,7 +247,9 @@ test_expect_failure 'ls-remote with filtered symref (--heads)' '
        1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/foo
        1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/master
        EOF
-       git ls-remote --symref --heads . >actual &&
+       # Protocol v2 supports sending symrefs for refs other than HEAD, so use
+       # protocol v0 here.
+       GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref --heads . >actual &&
        test_cmp expect actual
 '
 
@@ -252,9 +258,11 @@ test_expect_success 'ls-remote --symref omits filtered-out matches' '
        1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/foo
        1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/master
        EOF
-       git ls-remote --symref --heads . >actual &&
+       # Protocol v2 supports sending symrefs for refs other than HEAD, so use
+       # protocol v0 here.
+       GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref --heads . >actual &&
        test_cmp expect actual &&
-       git ls-remote --symref . "refs/heads/*" >actual &&
+       GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref . "refs/heads/*" >actual &&
        test_cmp expect actual
 '
 
index 36b0dbc01cffc06aefb180179965ccbaa9c983d8..e55d8474efb6891d4bea9edf5488f793b26e135a 100755 (executable)
@@ -6,6 +6,10 @@
 
 test_description='Merge logic in fetch'
 
+# NEEDSWORK: If the overspecification of the expected result is reduced, we
+# might be able to run this test in all protocol versions.
+GIT_TEST_PROTOCOL_VERSION=
+
 . ./test-lib.sh
 
 LF='
index 37e8e80893dad130c5c00882796047417aae115b..4bfbb7965476991e41c042b47e74ef9c6187efcc 100755 (executable)
@@ -1147,8 +1147,12 @@ test_expect_success 'fetch exact SHA1' '
                git prune &&
                test_must_fail git cat-file -t $the_commit &&
 
+               # Some protocol versions (e.g. 2) support fetching
+               # unadvertised objects, so restrict this test to v0.
+
                # fetching the hidden object should fail by default
-               test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
+               test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
+                       git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err &&
                test_i18ngrep "Server does not allow request for unadvertised object" err &&
                test_must_fail git rev-parse --verify refs/heads/copy &&
 
@@ -1204,7 +1208,10 @@ do
                mk_empty shallow &&
                (
                        cd shallow &&
-                       test_must_fail git fetch --depth=1 ../testrepo/.git $SHA1 &&
+                       # Some protocol versions (e.g. 2) support fetching
+                       # unadvertised objects, so restrict this test to v0.
+                       test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
+                               git fetch --depth=1 ../testrepo/.git $SHA1 &&
                        git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&
                        git fetch --depth=1 ../testrepo/.git $SHA1 &&
                        git cat-file commit $SHA1
@@ -1232,15 +1239,20 @@ do
                mk_empty shallow &&
                (
                        cd shallow &&
-                       test_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_3 &&
-                       test_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_1 &&
+                       # Some protocol versions (e.g. 2) support fetching
+                       # unadvertised objects, so restrict this test to v0.
+                       test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \
+                               git fetch ../testrepo/.git $SHA1_3 &&
+                       test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \
+                               git fetch ../testrepo/.git $SHA1_1 &&
                        git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&
                        git fetch ../testrepo/.git $SHA1_1 &&
                        git cat-file commit $SHA1_1 &&
                        test_must_fail git cat-file commit $SHA1_2 &&
                        git fetch ../testrepo/.git $SHA1_2 &&
                        git cat-file commit $SHA1_2 &&
-                       test_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_3
+                       test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \
+                               git fetch ../testrepo/.git $SHA1_3
                )
        '
 done
index 5fbf67c4468897184f46ef9ea151f1dd6ad1d8d0..cdb687b93aa1fe541a8c1b98a7dff0f4caf4c376 100755 (executable)
@@ -67,7 +67,10 @@ test_expect_success 'no shallow lines after receiving ACK ready' '
                cd clone &&
                git checkout --orphan newnew &&
                test_commit new-too &&
-               GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" git fetch --depth=2 &&
+               # NEEDSWORK: If the overspecification of the expected result is reduced, we
+               # might be able to run this test in all protocol versions.
+               GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" GIT_TEST_PROTOCOL_VERSION= \
+                       git fetch --depth=2 &&
                grep "fetch-pack< ACK .* ready" ../trace &&
                ! grep "fetch-pack> done" ../trace
        )
index 5475afc052934677c4f87adf4f29da507b4c6844..0e3055ab98b94596eb5f7ac65e9dc35c58cd24c2 100755 (executable)
@@ -47,7 +47,12 @@ test_expect_success 'no empty path components' '
        cd "$ROOT_PATH" &&
        git clone $HTTPD_URL/smart/test_repo.git/ test_repo_clone &&
 
-       check_access_log exp
+       # NEEDSWORK: If the overspecification of the expected result is reduced, we
+       # might be able to run this test in all protocol versions.
+       if test -z "$GIT_TEST_PROTOCOL_VERSION"
+       then
+               check_access_log exp
+       fi
 '
 
 test_expect_success 'clone remote repository' '
@@ -128,7 +133,12 @@ GET  /smart/test_repo.git/info/refs?service=git-receive-pack HTTP/1.1 200
 POST /smart/test_repo.git/git-receive-pack HTTP/1.1 200
 EOF
 test_expect_success 'used receive-pack service' '
-       check_access_log exp
+       # NEEDSWORK: If the overspecification of the expected result is reduced, we
+       # might be able to run this test in all protocol versions.
+       if test -z "$GIT_TEST_PROTOCOL_VERSION"
+       then
+               check_access_log exp
+       fi
 '
 
 test_http_push_nonff "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git \
index ba83e567e5ca49c1664fe13f447e2744d55bfb3a..a685d3edb66d197cef137186f667a7b4123e0f13 100755 (executable)
@@ -43,7 +43,8 @@ test_expect_success 'clone http repository' '
        < Cache-Control: no-cache, max-age=0, must-revalidate
        < Content-Type: application/x-git-upload-pack-result
        EOF
-       GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
+       GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION= \
+               git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
        test_cmp file clone/file &&
        tr '\''\015'\'' Q <err |
        sed -e "
@@ -80,12 +81,18 @@ test_expect_success 'clone http repository' '
                /^< Content-Length: /d
                /^< Transfer-Encoding: /d
        " >actual &&
-       sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \
-                       actual >actual.smudged &&
-       test_cmp exp actual.smudged &&
 
-       grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
-       test_line_count = 2 actual.gzip
+       # NEEDSWORK: If the overspecification of the expected result is reduced, we
+       # might be able to run this test in all protocol versions.
+       if test -z "$GIT_TEST_PROTOCOL_VERSION"
+       then
+               sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \
+                               actual >actual.smudged &&
+               test_cmp exp actual.smudged &&
+
+               grep "Accept-Encoding:.*gzip" actual >actual.gzip &&
+               test_line_count = 2 actual.gzip
+       fi
 '
 
 test_expect_success 'fetch changes via http' '
@@ -103,7 +110,13 @@ test_expect_success 'used upload-pack service' '
        GET  /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 200
        POST /smart/repo.git/git-upload-pack HTTP/1.1 200
        EOF
-       check_access_log exp
+
+       # NEEDSWORK: If the overspecification of the expected result is reduced, we
+       # might be able to run this test in all protocol versions.
+       if test -z "$GIT_TEST_PROTOCOL_VERSION"
+       then
+               check_access_log exp
+       fi
 '
 
 test_expect_success 'follow redirects (301)' '
@@ -215,8 +228,14 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set
        git config http.cookiefile cookies.txt &&
        git config http.savecookies true &&
        git ls-remote $HTTPD_URL/smart_cookies/repo.git master &&
-       tail -3 cookies.txt | sort >cookies_tail.txt &&
-       test_cmp expect_cookies.txt cookies_tail.txt
+
+       # NEEDSWORK: If the overspecification of the expected result is reduced, we
+       # might be able to run this test in all protocol versions.
+       if test -z "$GIT_TEST_PROTOCOL_VERSION"
+       then
+               tail -3 cookies.txt | sort >cookies_tail.txt &&
+               test_cmp expect_cookies.txt cookies_tail.txt
+       fi
 '
 
 test_expect_success 'transfer.hiderefs works over smart-http' '
@@ -306,7 +325,10 @@ test_expect_success 'test allowreachablesha1inwant with unreachable' '
 
        git init --bare test_reachable.git &&
        git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
-       test_must_fail git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
+       # Some protocol versions (e.g. 2) support fetching
+       # unadvertised objects, so restrict this test to v0.
+       test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
+               git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
 '
 
 test_expect_success 'test allowanysha1inwant with unreachable' '
@@ -325,7 +347,10 @@ test_expect_success 'test allowanysha1inwant with unreachable' '
 
        git init --bare test_reachable.git &&
        git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" &&
-       test_must_fail git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" &&
+       # Some protocol versions (e.g. 2) support fetching
+       # unadvertised objects, so restrict this test to v0.
+       test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
+               git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" &&
 
        git -C "$server" config uploadpack.allowanysha1inwant 1 &&
        git -C test_reachable.git fetch origin "$(git rev-parse HEAD)"
index 30857b84a8d5b5fdec59f775ab97293a7da4f2df..8a14be51a13280d3fccd340c027cd5f20bb941a5 100755 (executable)
@@ -127,7 +127,10 @@ test_expect_success 'use ref advertisement to filter out commits' '
        # not need to send any ancestors of "c3", but we still need to send "c3"
        # itself.
        test_config -C client fetch.negotiationalgorithm skipping &&
-       trace_fetch client origin to_fetch &&
+
+       # The ref advertisement itself is filtered when protocol v2 is used, so
+       # use v0.
+       GIT_TEST_PROTOCOL_VERSION= trace_fetch client origin to_fetch &&
        have_sent c5 c4^ c2side &&
        have_not_sent c4 c4^^ c4^^^
 '
index d6948cbdab03cf827d86511ade26366e89fda149..a454b143ea820392a8d41712d587cb144fc9a3df 100755 (executable)
@@ -345,7 +345,7 @@ expect_ssh () {
 }
 
 test_expect_success 'clone myhost:src uses ssh' '
-       git clone myhost:src ssh-clone &&
+       GIT_TEST_PROTOCOL_VERSION=0 git clone myhost:src ssh-clone &&
        expect_ssh myhost src
 '
 
@@ -356,12 +356,12 @@ test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
 '
 
 test_expect_success 'bracketed hostnames are still ssh' '
-       git clone "[myhost:123]:src" ssh-bracket-clone &&
+       GIT_TEST_PROTOCOL_VERSION=0 git clone "[myhost:123]:src" ssh-bracket-clone &&
        expect_ssh "-p 123" myhost src
 '
 
 test_expect_success 'OpenSSH variant passes -4' '
-       git clone -4 "[myhost:123]:src" ssh-ipv4-clone &&
+       GIT_TEST_PROTOCOL_VERSION=0 git clone -4 "[myhost:123]:src" ssh-ipv4-clone &&
        expect_ssh "-4 -p 123" myhost src
 '
 
@@ -405,7 +405,7 @@ test_expect_success 'OpenSSH-like uplink is treated as ssh' '
        test_when_finished "rm -f \"\$TRASH_DIRECTORY/uplink\"" &&
        GIT_SSH="$TRASH_DIRECTORY/uplink" &&
        test_when_finished "GIT_SSH=\"\$TRASH_DIRECTORY/ssh\$X\"" &&
-       git clone "[myhost:123]:src" ssh-bracket-clone-sshlike-uplink &&
+       GIT_TEST_PROTOCOL_VERSION=0 git clone "[myhost:123]:src" ssh-bracket-clone-sshlike-uplink &&
        expect_ssh "-p 123" myhost src
 '
 
@@ -444,14 +444,14 @@ test_expect_success 'single quoted plink.exe in GIT_SSH_COMMAND' '
 
 test_expect_success 'GIT_SSH_VARIANT overrides plink detection' '
        copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
-       GIT_SSH_VARIANT=ssh \
-       git clone "[myhost:123]:src" ssh-bracket-clone-variant-1 &&
+       GIT_TEST_PROTOCOL_VERSION=0 GIT_SSH_VARIANT=ssh \
+               git clone "[myhost:123]:src" ssh-bracket-clone-variant-1 &&
        expect_ssh "-p 123" myhost src
 '
 
 test_expect_success 'ssh.variant overrides plink detection' '
        copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink" &&
-       git -c ssh.variant=ssh \
+       GIT_TEST_PROTOCOL_VERSION=0 git -c ssh.variant=ssh \
                clone "[myhost:123]:src" ssh-bracket-clone-variant-2 &&
        expect_ssh "-p 123" myhost src
 '
@@ -482,7 +482,7 @@ counter=0
 # $3 path
 test_clone_url () {
        counter=$(($counter + 1))
-       test_might_fail git clone "$1" tmp$counter &&
+       test_might_fail env GIT_TEST_PROTOCOL_VERSION=0 git clone "$1" tmp$counter &&
        shift &&
        expect_ssh "$@"
 }
index ba86a44eb183921e844dff6f9d6a5bb27c7d5e91..d5ed196bfd096f1153c392f25a841aff3a84d7ca 100755 (executable)
@@ -4,6 +4,9 @@ test_description='test git wire-protocol transition'
 
 TEST_NO_CREATE_REPO=1
 
+# This is a protocol-specific test.
+GIT_TEST_PROTOCOL_VERSION=
+
 . ./test-lib.sh
 
 # Test protocol v1 with 'git://' transport
index db4ae09f2f81ff77b9c29b99c21363e66c81f222..e112b6086c96e4cb0ad7bc10dcd685e7570d496f 100755 (executable)
@@ -542,7 +542,38 @@ test_expect_success 'clone with http:// using protocol v2' '
        # Client requested to use protocol v2
        grep "Git-Protocol: version=2" log &&
        # Server responded using protocol v2
-       grep "git< version 2" log
+       grep "git< version 2" log &&
+       # Verify that the chunked encoding sending codepath is NOT exercised
+       ! grep "Send header: Transfer-Encoding: chunked" log
+'
+
+test_expect_success 'clone big repository with http:// using protocol v2' '
+       test_when_finished "rm -f log" &&
+
+       git init "$HTTPD_DOCUMENT_ROOT_PATH/big" &&
+       # Ensure that the list of wants is greater than http.postbuffer below
+       for i in $(test_seq 1 1500)
+       do
+               # do not use here-doc, because it requires a process
+               # per loop iteration
+               echo "commit refs/heads/too-many-refs-$i" &&
+               echo "committer git <git@example.com> $i +0000" &&
+               echo "data 0" &&
+               echo "M 644 inline bla.txt" &&
+               echo "data 4" &&
+               echo "bla"
+       done | git -C "$HTTPD_DOCUMENT_ROOT_PATH/big" fast-import &&
+
+       GIT_TRACE_PACKET="$(pwd)/log" GIT_TRACE_CURL="$(pwd)/log" git \
+               -c protocol.version=2 -c http.postbuffer=65536 \
+               clone "$HTTPD_URL/smart/big" big_child &&
+
+       # Client requested to use protocol v2
+       grep "Git-Protocol: version=2" log &&
+       # Server responded using protocol v2
+       grep "git< version 2" log &&
+       # Verify that the chunked encoding sending codepath is exercised
+       grep "Send header: Transfer-Encoding: chunked" log
 '
 
 test_expect_success 'fetch with http:// using protocol v2' '
index 55835ee4a47158e1f7aeaa9aeb393f1f3d619791..49a394bd75dde817700850187966c3d31ae03f17 100755 (executable)
@@ -681,7 +681,7 @@ test_expect_success 'bisect: --no-checkout - target in breakage' '
        check_same BROKEN_HASH6 BISECT_HEAD &&
        git bisect bad BISECT_HEAD &&
        check_same BROKEN_HASH5 BISECT_HEAD &&
-       git bisect good BISECT_HEAD &&
+       test_must_fail git bisect good BISECT_HEAD &&
        check_same BROKEN_HASH6 bisect/bad &&
        git bisect reset
 '
@@ -692,7 +692,7 @@ test_expect_success 'bisect: --no-checkout - target after breakage' '
        check_same BROKEN_HASH6 BISECT_HEAD &&
        git bisect good BISECT_HEAD &&
        check_same BROKEN_HASH8 BISECT_HEAD &&
-       git bisect good BISECT_HEAD &&
+       test_must_fail git bisect good BISECT_HEAD &&
        check_same BROKEN_HASH9 bisect/bad &&
        git bisect reset
 '
@@ -701,7 +701,7 @@ test_expect_success 'bisect: demonstrate identification of damage boundary' "
        git bisect reset &&
        git checkout broken &&
        git bisect start broken master --no-checkout &&
-       git bisect run \"\$SHELL_PATH\" -c '
+       test_must_fail git bisect run \"\$SHELL_PATH\" -c '
                GOOD=\$(git for-each-ref \"--format=%(objectname)\" refs/bisect/good-*) &&
                git rev-list --objects BISECT_HEAD --not \$GOOD >tmp.\$\$ &&
                git pack-objects --stdout >/dev/null < tmp.\$\$
index e87164aa8ffdba169ba6f91af99ae3d28f28459b..c973278300a5c911845016ef1e23144f51ebcd7d 100755 (executable)
@@ -943,7 +943,10 @@ test_expect_success 'submodule update clone shallow submodule outside of depth'
                cd super3 &&
                sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp &&
                mv -f .gitmodules.tmp .gitmodules &&
-               test_must_fail git submodule update --init --depth=1 2>actual &&
+               # Some protocol versions (e.g. 2) support fetching
+               # unadvertised objects, so restrict this test to v0.
+               test_must_fail env GIT_TEST_PROTOCOL_VERSION= \
+                       git submodule update --init --depth=1 2>actual &&
                test_i18ngrep "Direct fetching of that commit failed." actual &&
                git -C ../submodule config uploadpack.allowReachableSHA1InWant true &&
                git submodule update --init --depth=1 >actual &&
index f5e21bf970f4dc44c7fa30d54134a15cf343ffc1..43cf313a1c09ad8fb223ba775d5548c3f00c339c 100755 (executable)
@@ -1484,6 +1484,12 @@ test_expect_success 'git --help completion' '
        test_completion "git --help core" "core-tutorial "
 '
 
+test_expect_success 'completion.commands removes multiple commands' '
+       test_config completion.commands "-cherry -mergetool" &&
+       git --list-cmds=list-mainporcelain,list-complete,config >out &&
+       ! grep -E "^(cherry|mergetool)$" out
+'
+
 test_expect_success 'setup for integration tests' '
        echo content >file1 &&
        echo more >file2 &&
index 80402a428f7735a031658a904d4f623f38e43464..681c41ba329a90db8c668fde4640025872f1e622 100644 (file)
@@ -593,6 +593,15 @@ test_dir_is_empty () {
        fi
 }
 
+# Check if the file exists and has a size greater than zero
+test_file_not_empty () {
+       if ! test -s "$1"
+       then
+               echo "'$1' is not a non-empty file."
+               false
+       fi
+}
+
 test_path_is_missing () {
        if test -e "$1"
        then
index 4e79e140c90ba5aa8cdbe7daeafba45765cecd8e..562c57e6858b79aff074fcb7ab8c65fa2f110bc0 100644 (file)
@@ -147,10 +147,16 @@ do
        --stress)
                stress=t ;;
        --stress=*)
+               echo "error: --stress does not accept an argument: '$opt'" >&2
+               echo "did you mean --stress-jobs=${opt#*=} or --stress-limit=${opt#*=}?" >&2
+               exit 1
+               ;;
+       --stress-jobs=*)
+               stress=t;
                stress=${opt#--*=}
                case "$stress" in
                *[!0-9]*|0*|"")
-                       echo "error: --stress=<N> requires the number of jobs to run" >&2
+                       echo "error: --stress-jobs=<N> requires the number of jobs to run" >&2
                        exit 1
                        ;;
                *)      # Good.
@@ -158,6 +164,7 @@ do
                esac
                ;;
        --stress-limit=*)
+               stress=t;
                stress_limit=${opt#--*=}
                case "$stress_limit" in
                *[!0-9]*|0*|"")
index 22c41a3ba80971e5edc6bbf02eb6ea59d3c41277..1ccd343cad92dfad3e66deb304811eaf7af9b4fc 100644 (file)
@@ -2386,7 +2386,7 @@ int oneway_merge(const struct cache_entry * const *src,
                if (o->update && S_ISGITLINK(old->ce_mode) &&
                    should_update_submodules() && !verify_uptodate(old, o))
                        update |= CE_UPDATE;
-               add_entry(o, old, update, 0);
+               add_entry(o, old, update, CE_STAGEMASK);
                return 0;
        }
        return merged_entry(a, old, o);
index d6a0ee7f730d96a7e8cc04095ddafb43c937105a..b45bfeb9d33b4ae4f372a15edd90651bf3735f92 100644 (file)
@@ -444,7 +444,7 @@ int submodule_uses_worktrees(const char *path)
        DIR *dir;
        struct dirent *d;
        int ret = 0;
-       struct repository_format format;
+       struct repository_format format = REPOSITORY_FORMAT_INIT;
 
        submodule_gitdir = git_pathdup_submodule(path, "%s", "");
        if (!submodule_gitdir)
@@ -462,8 +462,10 @@ int submodule_uses_worktrees(const char *path)
        read_repository_format(&format, sb.buf);
        if (format.version != 0) {
                strbuf_release(&sb);
+               clear_repository_format(&format);
                return 1;
        }
+       clear_repository_format(&format);
 
        /* Replace config by worktrees. */
        strbuf_setlen(&sb, sb.len - strlen("config"));
index 80f060d2782e227ce7637a41d05742729c48f6ac..8509f9ea223a1282a367874c3e3a3ef0c351a30f 100644 (file)
@@ -306,6 +306,10 @@ int git_xmerge_config(const char *var, const char *value, void *cb)
                        git_xmerge_style = XDL_MERGE_DIFF3;
                else if (!strcmp(value, "merge"))
                        git_xmerge_style = 0;
+               /*
+                * Please update _git_checkout() in
+                * git-completion.bash when you add new merge config
+                */
                else
                        die("unknown style '%s' given for '%s'",
                            value, var);