Merge branch 'ls/clean-smudge-override-in-config'
authorJunio C Hamano <gitster@pobox.com>
Wed, 10 Feb 2016 22:20:07 +0000 (14:20 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Feb 2016 22:20:07 +0000 (14:20 -0800)
Clean/smudge filters defined in a configuration file of lower
precedence can now be overridden to be a pass-through no-op by
setting the variable to an empty string.

* ls/clean-smudge-override-in-config:
convert: treat an empty string for clean/smudge filters as "cat"

275 files changed:
.travis.yml
Documentation/RelNotes/2.7.1.txt [new file with mode: 0644]
Documentation/RelNotes/2.8.0.txt [new file with mode: 0644]
Documentation/blame-options.txt
Documentation/config.txt
Documentation/fetch-options.txt
Documentation/git-add.txt
Documentation/git-am.txt
Documentation/git-blame.txt
Documentation/git-cherry-pick.txt
Documentation/git-clone.txt
Documentation/git-commit.txt
Documentation/git-for-each-ref.txt
Documentation/git-format-patch.txt
Documentation/git-grep.txt
Documentation/git-interpret-trailers.txt
Documentation/git-ls-files.txt
Documentation/git-ls-remote.txt
Documentation/git-pull.txt
Documentation/git-push.txt
Documentation/git-revert.txt
Documentation/git-tag.txt
Documentation/git-update-index.txt
Documentation/git-worktree.txt
Documentation/git.txt
Documentation/gitignore.txt
Documentation/glossary-content.txt
Documentation/pretty-options.txt
Documentation/revisions.txt
Documentation/technical/api-remote.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
bisect.c
builtin/am.c
builtin/blame.c
builtin/cat-file.c
builtin/check-attr.c
builtin/check-ignore.c
builtin/check-mailmap.c
builtin/checkout-index.c
builtin/checkout.c
builtin/clean.c
builtin/clone.c
builtin/column.c
builtin/commit.c
builtin/diff.c
builtin/fast-export.c
builtin/fetch-pack.c
builtin/fetch.c
builtin/grep.c
builtin/hash-object.c
builtin/interpret-trailers.c
builtin/log.c
builtin/ls-files.c
builtin/ls-remote.c
builtin/merge.c
builtin/mktree.c
builtin/notes.c
builtin/pull.c
builtin/push.c
builtin/receive-pack.c
builtin/remote.c
builtin/repack.c
builtin/rev-parse.c
builtin/rm.c
builtin/send-pack.c
builtin/shortlog.c
builtin/tag.c
builtin/update-index.c
cache-tree.c
cache.h
compat/basename.c
compat/bswap.h
compat/mingw.c
compat/mingw.h
compat/nedmalloc/malloc.c.h
compat/poll/poll.c
compat/terminal.c
compat/win32/pthread.h
compat/winansi.c
config.c
config.mak.uname
contrib/completion/git-completion.bash
contrib/examples/git-commit.sh
contrib/examples/git-fetch.sh
contrib/examples/git-merge.sh
contrib/examples/git-repack.sh
contrib/examples/git-revert.sh
contrib/subtree/Makefile
contrib/subtree/git-subtree.sh
contrib/subtree/t/t7900-subtree.sh
contrib/thunderbird-patch-inline/appp.sh
convert.c
convert.h
credential-cache--daemon.c
credential-store.c
credential.c
daemon.c
diff-no-index.c
diff.c
diff.h
dir.c
dir.h
environment.c
fast-import.c
git-compat-util.h
git-filter-branch.sh
git-gui/po/glossary/txt-to-pot.sh
git-p4.py
git-rebase.sh
git-send-email.perl
git.c
gitweb/gitweb.perl
http.c
http.h
ident.c
mailinfo.c
notes-cache.c
notes-utils.c
notes.c
notes.h
pack-bitmap.c
pack-revindex.c
pack-revindex.h
path.c
perl/Git/SVN/Ra.pm
read-cache.c
ref-filter.c
reflog-walk.c
refs.h
refs/files-backend.c
remote-curl.c
remote-testsvn.c
remote.c
remote.h
revision.c
run-command.c
run-command.h
sequencer.c
setup.c
sha1_file.c
shell.c
sigchain.c
sigchain.h
strbuf.c
strbuf.h
submodule.c
submodule.h
t/lib-httpd.sh
t/perf/p7300-clean.sh
t/t0001-init.sh
t/t0027-auto-crlf.sh
t/t0060-path-utils.sh
t/t0061-run-command.sh
t/t1100-commit-tree-options.sh
t/t1401-symbolic-ref.sh
t/t1410-reflog.sh
t/t1511-rev-parse-caret.sh
t/t1512-rev-parse-disambiguation.sh
t/t1700-split-index.sh
t/t2011-checkout-invalid-head.sh
t/t2025-worktree-add.sh
t/t2102-update-index-symlinks.sh
t/t3000-ls-files-others.sh
t/t3001-ls-files-others-exclude.sh
t/t3030-merge-recursive.sh
t/t3100-ls-tree-restrict.sh
t/t3101-ls-tree-dirname.sh
t/t3203-branch-output.sh
t/t3210-pack-refs.sh
t/t3301-notes.sh
t/t3308-notes-merge.sh
t/t3403-rebase-skip.sh
t/t3511-cherry-pick-x.sh
t/t3600-rm.sh
t/t3700-add.sh
t/t4014-format-patch.sh
t/t4056-diff-order.sh
t/t4201-shortlog.sh
t/t5100-mailinfo.sh
t/t5300-pack-object.sh
t/t5301-sliding-window.sh
t/t5302-pack-index.sh
t/t5303-pack-corruption-resilience.sh
t/t5304-prune.sh
t/t5305-include-tag.sh
t/t5500-fetch-pack.sh
t/t5505-remote.sh
t/t5506-remote-groups.sh
t/t5510-fetch.sh
t/t5512-ls-remote.sh
t/t5515-fetch-merge-logic.sh
t/t5516-fetch-push.sh
t/t5517-push-mirror.sh
t/t5520-pull.sh
t/t5522-pull-symlink.sh
t/t5526-fetch-submodules.sh
t/t5530-upload-pack-error.sh
t/t5532-fetch-proxy.sh
t/t5537-fetch-shallow.sh
t/t5538-push-shallow.sh
t/t5550-http-fetch-dumb.sh
t/t5570-git-daemon.sh
t/t5601-clone.sh
t/t5700-clone-reference.sh
t/t5710-info-alternate.sh
t/t5900-repo-selection.sh
t/t6001-rev-list-graft.sh
t/t6002-rev-list-bisect.sh
t/t6015-rev-list-show-all-parents.sh
t/t6023-merge-file.sh
t/t6032-merge-large-rename.sh
t/t6050-replace.sh
t/t6132-pathspec-exclude.sh
t/t6300-for-each-ref.sh
t/t7001-mv.sh
t/t7003-filter-branch.sh
t/t7004-tag.sh
t/t7006-pager.sh
t/t7063-status-untracked-cache.sh
t/t7103-reset-bare.sh
t/t7406-submodule-update.sh
t/t7408-submodule-reference.sh
t/t7504-commit-msg-hook.sh
t/t7505-prepare-commit-msg-hook.sh
t/t7513-interpret-trailers.sh
t/t7602-merge-octopus-many.sh
t/t7700-repack.sh
t/t7810-grep.sh
t/t8003-blame-corner-cases.sh
t/t9001-send-email.sh
t/t9100-git-svn-basic.sh
t/t9101-git-svn-props.sh
t/t9104-git-svn-follow-parent.sh
t/t9105-git-svn-commit-diff.sh
t/t9107-git-svn-migrate.sh
t/t9108-git-svn-glob.sh
t/t9109-git-svn-multi-glob.sh
t/t9110-git-svn-use-svm-props.sh
t/t9114-git-svn-dcommit-merge.sh
t/t9118-git-svn-funky-branch-names.sh
t/t9119-git-svn-info.sh
t/t9129-git-svn-i18n-commitencoding.sh
t/t9130-git-svn-authors-file.sh
t/t9132-git-svn-broken-symlink.sh
t/t9137-git-svn-dcommit-clobber-series.sh
t/t9138-git-svn-authors-prog.sh
t/t9145-git-svn-master-branch.sh
t/t9150-svk-mergetickets.sh
t/t9300-fast-import.sh
t/t9350-fast-export.sh
t/t9501-gitweb-standalone-http-status.sh
t/t9827-git-p4-change-filetype.sh [new file with mode: 0755]
t/t9901-git-web--browse.sh
t/test-lib.sh
test-dump-untracked-cache.c
test-path-utils.c
test-run-command.c
test-sha1-array.c
test-sha1.sh
trailer.c
trailer.h
transport-helper.c
transport.c
tree-walk.c
tree-walk.h
unimplemented.sh
unpack-trees.c
walker.c
worktree.c
wrapper.c
wt-status.c
xdiff/xmerge.c
index c3bf9c6d4d1c6049dd38a5a861dceb4c8e1b7e99..f8b73ec3da4e998f673296d093a89d8e9e53ba24 100644 (file)
@@ -1,5 +1,11 @@
 language: c
 
+sudo: false
+
+cache:
+  directories:
+    - $HOME/travis-cache
+
 os:
   - linux
   - osx
@@ -18,7 +24,7 @@ env:
     - P4_VERSION="15.2"
     - GIT_LFS_VERSION="1.1.0"
     - DEFAULT_TEST_TARGET=prove
-    - GIT_PROVE_OPTS="--timer --jobs 3"
+    - GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save"
     - GIT_TEST_OPTS="--verbose --tee"
     - CFLAGS="-g -O2 -Wall -Werror"
     - GIT_TEST_CLONE_2GB=YesPlease
@@ -67,6 +73,8 @@ before_install:
     p4 -V | grep Rev.;
     echo "$(tput setaf 6)Git-LFS Version$(tput sgr0)";
     git-lfs version;
+    mkdir -p $HOME/travis-cache;
+    ln -s $HOME/travis-cache/.prove t/.prove;
 
 before_script: make --jobs=2
 
diff --git a/Documentation/RelNotes/2.7.1.txt b/Documentation/RelNotes/2.7.1.txt
new file mode 100644 (file)
index 0000000..6553d69
--- /dev/null
@@ -0,0 +1,87 @@
+Git v2.7.1 Release Notes
+========================
+
+Fixes since v2.7
+----------------
+
+ * An earlier change in 2.5.x-era broke users' hooks and aliases by
+   exporting GIT_WORK_TREE to point at the root of the working tree,
+   interfering when they tried to use a different working tree without
+   setting GIT_WORK_TREE environment themselves.
+
+ * The "exclude_list" structure has the usual "alloc, nr" pair of
+   fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot
+   to reset 'alloc' to 0 when it cleared 'nr' to discard the managed
+   array.
+
+ * "git send-email" was confused by escaped quotes stored in the alias
+   files saved by "mutt", which has been corrected.
+
+ * A few unportable C construct have been spotted by clang compiler
+   and have been fixed.
+
+ * The documentation has been updated to hint the connection between
+   the '--signoff' option and DCO.
+
+ * "git reflog" incorrectly assumed that all objects that used to be
+   at the tip of a ref must be commits, which caused it to segfault.
+
+ * The ignore mechanism saw a few regressions around untracked file
+   listing and sparse checkout selection areas in 2.7.0; the change
+   that is responsible for the regression has been reverted.
+
+ * Some codepaths used fopen(3) when opening a fixed path in $GIT_DIR
+   (e.g. COMMIT_EDITMSG) that is meant to be left after the command is
+   done.  This however did not work well if the repository is set to
+   be shared with core.sharedRepository and the umask of the previous
+   user is tighter.  They have been made to work better by calling
+   unlink(2) and retrying after fopen(3) fails with EPERM.
+
+ * Asking gitweb for a nonexistent commit left a warning in the server
+   log.
+
+ * "git rebase", unlike all other callers of "gc --auto", did not
+   ignore the exit code from "gc --auto".
+
+ * Many codepaths that run "gc --auto" before exiting kept packfiles
+   mapped and left the file descriptors to them open, which was not
+   friendly to systems that cannot remove files that are open.  They
+   now close the packs before doing so.
+
+ * A recent optimization to filter-branch in v2.7.0 introduced a
+   regression when --prune-empty filter is used, which has been
+   corrected.
+
+ * The description for SANITY prerequisite the test suite uses has
+   been clarified both in the comment and in the implementation.
+
+ * "git tag" started listing a tag "foo" as "tags/foo" when a branch
+   named "foo" exists in the same repository; remove this unnecessary
+   disambiguation, which is a regression introduced in v2.7.0.
+
+ * The way "git svn" uses auth parameter was broken by Subversion
+   1.9.0 and later.
+
+ * The "split" subcommand of "git subtree" (in contrib/) incorrectly
+   skipped merges when it shouldn't, which was corrected.
+
+ * A few options of "git diff" did not work well when the command was
+   run from a subdirectory.
+
+ * dirname() emulation has been added, as Msys2 lacks it.
+
+ * The underlying machinery used by "ls-files -o" and other commands
+   have been taught not to create empty submodule ref cache for a
+   directory that is not a submodule.  This removes a ton of wasted
+   CPU cycles.
+
+ * Drop a few old "todo" items by deciding that the change one of them
+   suggests is not such a good idea, and doing the change the other
+   one suggested to do.
+
+ * Documentation for "git fetch --depth" has been updated for clarity.
+
+ * The command line completion learned a handful of additional options
+   and command specific syntax.
+
+Also includes a handful of documentation and test updates.
diff --git a/Documentation/RelNotes/2.8.0.txt b/Documentation/RelNotes/2.8.0.txt
new file mode 100644 (file)
index 0000000..166e06c
--- /dev/null
@@ -0,0 +1,235 @@
+Git 2.8 Release Notes
+=====================
+
+Updates since v2.7
+------------------
+
+UI, Workflows & Features
+
+ * "branch --delete" has "branch -d" but "push --delete" does not.
+
+ * "git blame" learned to produce the progress eye-candy when it takes
+   too much time before emitting the first line of the result.
+
+ * "git grep" can now be configured (or told from the command line)
+   how many threads to use when searching in the working tree files.
+
+ * Some "git notes" operations, e.g. "git log --notes=<note>", should
+   be able to read notes from any tree-ish that is shaped like a notes
+   tree, but the notes infrastructure required that the argument must
+   be a ref under refs/notes/.  Loosen it to require a valid ref only
+   when the operation would update the notes (in which case we must
+   have a place to store the updated notes tree, iow, a ref).
+
+ * "git grep" by default does not fall back to its "--no-index"
+   behaviour outside a directory under Git's control (otherwise the
+   user may by mistake end up running a huge recursive search); with a
+   new configuration (set in $HOME/.gitconfig--by definition this
+   cannot be set in the config file per project), this safety can be
+   disabled.
+
+ * "git pull --rebase" has been extended to allow invoking
+   "rebase -i".
+
+ * "git p4" learned to cope with the type of a file getting changed.
+
+ * "git format-patch" learned to notice format.outputDirectory
+   configuration variable.  This allows "-o <dir>" option to be
+   omitted on the command line if you always use the same directory in
+   your workflow.
+
+ * "interpret-trailers" has been taught to optionally update a file in
+   place, instead of always writing the result to the standard output.
+
+ * Many commands that read files that are expected to contain text
+   that is generated (or can be edited) by the end user to control
+   their behaviour (e.g. "git grep -f <filename>") have been updated
+   to be more tolerant to lines that are terminated with CRLF (they
+   used to treat such a line to contain payload that ends with CR,
+   which is usually not what the users expect).
+
+ * "git notes merge" used to limit the source of the merged notes tree
+   to somewhere under refs/notes/ hierarchy, which was too limiting
+   when inventing a workflow to exchange notes with remote
+   repositories using remote-tracking notes trees (located in e.g.
+   refs/remote-notes/ or somesuch).
+
+ * "git ls-files" learned a new "--eol" option to help diagnose
+   end-of-line problems.
+
+ * "ls-remote" learned an option to show which branch the remote
+   repository advertises as its primary by pointing its HEAD at.
+
+ * New http.proxyAuthMethod configuration variable can be used to
+   specify what authentication method to use, as a way to work around
+   proxies that do not give error response expected by libcurl when
+   CURLAUTH_ANY is used.  Also, the codepath for proxy authentication
+   has been taught to use credential API to store the authentication
+   material in user's keyrings.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * Add a framework to spawn a group of processes in parallel, and use
+   it to run "git fetch --recurse-submodules" in parallel.
+
+ * A slight update to the Makefile to mark "phoney" targets
+   as such correctly.
+
+ * In-core storage of the reverse index for .pack files (which lets
+   you go from a pack offset to an object name) has been streamlined.
+
+ * d95138e6 (setup: set env $GIT_WORK_TREE when work tree is set, like
+   $GIT_DIR, 2015-06-26) attempted to work around a glitch in alias
+   handling by overwriting GIT_WORK_TREE environment variable to
+   affect subprocesses when set_git_work_tree() gets called, which
+   resulted in a rather unpleasant regression to "clone" and "init".
+   Try to address the same issue by always restoring the environment
+   and respawning the real underlying command when handling alias.
+
+ * The low-level code that is used to create symbolic references has
+   been updated to share more code with the code that deals with
+   normal references.
+
+ * strbuf_getline() and friends have been redefined to make it easier
+   to identify which callsite of (new) strbuf_getline_lf() should
+   allow and silently ignore carriage-return at the end of the line to
+   help users on DOSsy systems.
+
+ * "git shortlog" used to accumulate various pieces of information
+   regardless of what was asked to be shown in the final output.  It
+   has been optimized by noticing what need not to be collected
+   (e.g. there is no need to collect the log messages when showing
+   only the number of changes).
+
+ * "git checkout $branch" (and other operations that share the same
+   underlying machinery) has been optimized.
+
+ * Automated tests in Travis CI environment has been optimized by
+   persisting runtime statistics of previous "prove" run, executing
+   tests that take longer before other ones; this reduces the total
+   wallclock time.
+
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v2.7
+----------------
+
+Unless otherwise noted, all the fixes since v2.7 in the maintenance
+track are contained in this release (see the maintenance releases'
+notes for details).
+
+ * An earlier change in 2.5.x-era broke users' hooks and aliases by
+   exporting GIT_WORK_TREE to point at the root of the working tree,
+   interfering when they tried to use a different working tree without
+   setting GIT_WORK_TREE environment themselves.
+   (merge df1e6ea nd/stop-setenv-work-tree later to maint).
+
+ * The "exclude_list" structure has the usual "alloc, nr" pair of
+   fields to be used by ALLOC_GROW(), but clear_exclude_list() forgot
+   to reset 'alloc' to 0 when it cleared 'nr' to discard the managed
+   array.
+   (merge 2653a8c nd/dir-exclude-cleanup later to maint).
+
+ * Paths that have been told the index about with "add -N" are not
+   quite yet in the index, but a few commands behaved as if they
+   already are in a harmful way.
+   (merge 4d55200 nd/ita-cleanup later to maint).
+
+ * "git send-email" was confused by escaped quotes stored in the alias
+   files saved by "mutt", which has been corrected.
+   (merge 2c510f2 ew/send-email-mutt-alias-fix later to maint).
+
+ * A few unportable C construct have been spotted by clang compiler
+   and have been fixed.
+   (merge a0df2e5 jk/clang-pedantic later to maint).
+
+ * The documentation has been updated to hint the connection between
+   the '--signoff' option and DCO.
+   (merge b2c150d dw/signoff-doc later to maint).
+
+ * "git reflog" incorrectly assumed that all objects that used to be
+   at the tip of a ref must be commits, which caused it to segfault.
+   (merge aecad37 dk/reflog-walk-with-non-commit later to maint).
+
+ * The ignore mechanism saw a few regressions around untracked file
+   listing and sparse checkout selection areas in 2.7.0; the change
+   that is responsible for the regression has been reverted.
+   (merge 8c72236 nd/exclusion-regression-fix later to maint).
+
+ * Some codepaths used fopen(3) when opening a fixed path in $GIT_DIR
+   (e.g. COMMIT_EDITMSG) that is meant to be left after the command is
+   done.  This however did not work well if the repository is set to
+   be shared with core.sharedRepository and the umask of the previous
+   user is tighter.  They have been made to work better by calling
+   unlink(2) and retrying after fopen(3) fails with EPERM.
+   (merge ea56518 js/fopen-harder later to maint).
+
+ * Asking gitweb for a nonexistent commit left a warning in the server
+   log.
+
+   Somebody may want to follow this up with an additional test, perhaps?
+   IIRC, we do test that no Perl warnings are given to the server log,
+   so this should have been caught if our test coverage were good.
+   (merge a9eb90a ho/gitweb-squelch-undef-warning later to maint).
+
+ * "git rebase", unlike all other callers of "gc --auto", did not
+   ignore the exit code from "gc --auto".
+   (merge 8c24f5b jk/ok-to-fail-gc-auto-in-rebase later to maint).
+
+ * Many codepaths that run "gc --auto" before exiting kept packfiles
+   mapped and left the file descriptors to them open, which was not
+   friendly to systems that cannot remove files that are open.  They
+   now close the packs before doing so.
+   (merge d562102 js/close-packs-before-gc later to maint).
+
+ * A recent optimization to filter-branch in v2.7.0 introduced a
+   regression when --prune-empty filter is used, which has been
+   corrected.
+   (merge 1dc413e jk/filter-branch-no-index later to maint).
+
+ * The description for SANITY prerequisite the test suite uses has
+   been clarified both in the comment and in the implementation.
+   (merge 719c3da jk/sanity later to maint).
+
+ * "git tag" started listing a tag "foo" as "tags/foo" when a branch
+   named "foo" exists in the same repository; remove this unnecessary
+   disambiguation, which is a regression introduced in v2.7.0.
+   (merge 0571979 jk/list-tag-2.7-regression later to maint).
+
+ * The way "git svn" uses auth parameter was broken by Subversion
+   1.9.0 and later.
+   (merge 0b66415 ew/svn-1.9.0-auth later to maint).
+
+ * The "split" subcommand of "git subtree" (in contrib/) incorrectly
+   skipped merges when it shouldn't, which was corrected.
+   (merge 933cfeb dw/subtree-split-do-not-drop-merge later to maint).
+
+ * A few options of "git diff" did not work well when the command was
+   run from a subdirectory.
+   (merge a97262c nd/diff-with-path-params later to maint).
+
+ * The command line completion learned a handful of additional options
+   and command specific syntax.
+   (merge fa4b5e3 jk/completion-rebase later to maint).
+   (merge f7c2e1a pw/completion-show-branch later to maint).
+   (merge d7d4ca8 pw/completion-stash later to maint).
+   (merge e6414b4 tb/complete-word-diff-regex later to maint).
+
+ * dirname() emulation has been added, as Msys2 lacks it.
+   (merge e7d5ce8 js/dirname-basename later to maint).
+
+ * The underlying machinery used by "ls-files -o" and other commands
+   have been taught not to create empty submodule ref cache for a
+   directory that is not a submodule.  This removes a ton of wasted
+   CPU cycles.
+   (merge a2d5156 jk/ref-cache-non-repository-optim later to maint).
+
+ * Other minor clean-ups and documentation updates
+   (merge 99487cf ss/user-manual later to maint).
+   (merge e914ef0 ew/for-each-ref-doc later to maint).
+   (merge 36fc7d8 sg/t6050-failing-editor-test-fix later to maint).
+   (merge 60253a6 ss/clone-depth-single-doc later to maint).
+   (merge bd02e97 lv/add-doc-working-tree later to maint).
index 760eab7428357ad4006437ae3032cee958dce803..02cb6845cd96194b655c9898189c4d5f24ca6a92 100644 (file)
@@ -69,6 +69,13 @@ include::line-range-format.txt[]
        iso format is used. For supported values, see the discussion
        of the --date option at linkgit:git-log[1].
 
+--[no-]progress::
+       Progress status is reported on the standard error stream
+       by default when it is attached to a terminal. This flag
+       enables progress reporting even if not attached to a
+       terminal. Can't use `--progress` together with `--porcelain`
+       or `--incremental`.
+
 -M|<num>|::
        Detect moved or copied lines within a file. When a commit
        moves or copies a block of lines (e.g. the original file
index f61788668e89b659439e2fa5d600aebabdd733a5..27f02be35ed2aebedab93281814b1f4e0fea4f35 100644 (file)
@@ -308,6 +308,15 @@ core.trustctime::
        crawlers and some backup systems).
        See linkgit:git-update-index[1]. True by default.
 
+core.untrackedCache::
+       Determines what to do about the untracked cache feature of the
+       index. It will be kept, if this variable is unset or set to
+       `keep`. It will automatically be added if set to `true`. And
+       it will automatically be removed, if set to `false`. Before
+       setting it to `true`, you should check that mtime is working
+       properly on your system.
+       See linkgit:git-update-index[1]. `keep` by default.
+
 core.checkStat::
        Determines which stat fields to match between the index
        and work tree. The user can set this to 'default' or
@@ -870,6 +879,8 @@ 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 the value is `interactive`, the rebase is run in interactive mode.
++
 *NOTE*: this is a possibly dangerous operation; do *not* use
 it unless you understand the implications (see linkgit:git-rebase[1]
 for details).
@@ -1243,6 +1254,10 @@ format.coverLetter::
        format-patch is invoked, but in addition can be set to "auto", to
        generate a cover-letter only when there's more than one patch.
 
+format.outputDirectory::
+       Set a custom directory to store the resulting files instead of the
+       current working directory.
+
 filter.<driver>.clean::
        The command which is used to convert the content of a worktree
        file to a blob upon checkin.  See linkgit:gitattributes[5] for
@@ -1450,6 +1465,14 @@ grep.extendedRegexp::
        option is ignored when the 'grep.patternType' option is set to a value
        other than 'default'.
 
+grep.threads::
+       Number of grep worker threads to use.
+       See `grep.threads` in linkgit:git-grep[1] for more information.
+
+grep.fallbackToNoIndex::
+       If set to true, fall back to git grep --no-index if git grep
+       is executed outside of a git repository.  Defaults to false.
+
 gpg.program::
        Use this custom program instead of "gpg" found on $PATH when
        making or verifying a PGP signature. The program must support the
@@ -1596,9 +1619,34 @@ help.htmlPath::
 
 http.proxy::
        Override the HTTP proxy, normally configured using the 'http_proxy',
-       'https_proxy', and 'all_proxy' environment variables (see
-       `curl(1)`).  This can be overridden on a per-remote basis; see
-       remote.<name>.proxy
+       'https_proxy', and 'all_proxy' environment variables (see `curl(1)`). In
+       addition to the syntax understood by curl, it is possible to specify a
+       proxy string with a user name but no password, in which case git will
+       attempt to acquire one in the same way it does for other credentials. See
+       linkgit:gitcredentials[7] for more information. The syntax thus is
+       '[protocol://][user[:password]@]proxyhost[:port]'. This can be overridden
+       on a per-remote basis; see remote.<name>.proxy
+
+http.proxyAuthMethod::
+       Set the method with which to authenticate against the HTTP proxy. This
+       only takes effect if the configured proxy string contains a user name part
+       (i.e. is of the form 'user@host' or 'user@host:port'). This can be
+       overridden on a per-remote basis; see `remote.<name>.proxyAuthMethod`.
+       Both can be overridden by the 'GIT_HTTP_PROXY_AUTHMETHOD' environment
+       variable.  Possible values are:
++
+--
+* `anyauth` - Automatically pick a suitable authentication method. It is
+  assumed that the proxy answers an unauthenticated request with a 407
+  status code and one or more Proxy-authenticate headers with supported
+  authentication methods. This is the default.
+* `basic` - HTTP Basic authentication
+* `digest` - HTTP Digest authentication; this prevents the password from being
+  transmitted to the proxy in clear text
+* `negotiate` - GSS-Negotiate authentication (compare the --negotiate option
+  of `curl(1)`)
+* `ntlm` - NTLM authentication (compare the --ntlm option of `curl(1)`)
+--
 
 http.cookieFile::
        File containing previously stored cookie lines which should be used
@@ -2149,6 +2197,8 @@ 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 the value is `interactive`, the rebase is run in interactive mode.
++
 *NOTE*: this is a possibly dangerous operation; do *not* use
 it unless you understand the implications (see linkgit:git-rebase[1]
 for details).
@@ -2407,6 +2457,11 @@ remote.<name>.proxy::
        the proxy to use for that remote.  Set to the empty string to
        disable proxying for that remote.
 
+remote.<name>.proxyAuthMethod::
+       For remotes that require curl (http, https and ftp), the method to use for
+       authenticating against the proxy in use (probably set in
+       `remote.<name>.proxy`). See `http.proxyAuthMethod`.
+
 remote.<name>.fetch::
        The default set of "refspec" for linkgit:git-fetch[1]. See
        linkgit:git-fetch[1].
index 45583d8454b4cae9bdb2ddb904c077cf1d3a1223..952dfdfef098ca00b7976ef9d549401f171514f6 100644 (file)
@@ -8,10 +8,11 @@
        option old data in `.git/FETCH_HEAD` will be overwritten.
 
 --depth=<depth>::
-       Deepen or shorten the history of a 'shallow' repository created by
-       `git clone` with `--depth=<depth>` option (see linkgit:git-clone[1])
-       to the specified number of commits from the tip of each remote
-       branch history. Tags for the deepened commits are not fetched.
+       Limit fetching to the specified number of commits from the tip of
+       each remote branch history. If fetching to a 'shallow' repository
+       created by `git clone` with `--depth=<depth>` option (see
+       linkgit:git-clone[1]), deepen or shorten the history to the specified
+       number of commits. Tags for the deepened commits are not fetched.
 
 --unshallow::
        If the source repository is complete, convert a shallow
@@ -100,6 +101,13 @@ ifndef::git-pull[]
        reference to a commit that isn't already in the local submodule
        clone.
 
+-j::
+--jobs=<n>::
+       Number of parallel children to be used for fetching submodules.
+       Each will fetch from different submodules, such that fetching many
+       submodules will be faster. By default submodules will be fetched
+       one at a time.
+
 --no-recurse-submodules::
        Disable recursive fetching of submodules (this has the same effect as
        using the '--recurse-submodules=no' option).
index fe5282f1305902545eaff585ced432d296dd64f4..6a96a669c299ebd0408d3a1e34d8e42541f3a9e8 100644 (file)
@@ -24,7 +24,7 @@ remove paths that do not exist in the working tree anymore.
 
 The "index" holds a snapshot of the content of the working tree, and it
 is this snapshot that is taken as the contents of the next commit.  Thus
-after making any changes to the working directory, and before running
+after making any changes to the working tree, and before running
 the commit command, you must use the `add` command to add any new or
 modified files to the index.
 
index 452c1feb2319a3ac47836b5039ebeba519be3c87..13cdd7f3b636dfadc262dcf099653775ec53cd5a 100644 (file)
@@ -35,6 +35,7 @@ OPTIONS
 --signoff::
        Add a `Signed-off-by:` line to the commit message, using
        the committer identity of yourself.
+       See the signoff option in linkgit:git-commit[1] for more information.
 
 -k::
 --keep::
index e6e947c808d5e419a9d974d63ab7b95195b667c8..ba5417567c4df286a95a99cf1ae3e02ee466458f 100644 (file)
@@ -10,7 +10,8 @@ SYNOPSIS
 [verse]
 'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
            [-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
-           [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>] [--] <file>
+           [--progress] [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>]
+           [--] <file>
 
 DESCRIPTION
 -----------
index 77da29a474518c56c7dab23f5921aa50566506dd..6154e57238143b968b10deacf3ef6fb9d3ef1b86 100644 (file)
@@ -100,6 +100,7 @@ effect to your index in a row.
 -s::
 --signoff::
        Add Signed-off-by line at the end of the commit message.
+       See the signoff option in linkgit:git-commit[1] for more information.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
index 6bf000dac348880cc2f5b8d3cb6825e7a1ca82b4..789b668f7732957d71f42f98d361abd0b34305a7 100644 (file)
@@ -190,15 +190,14 @@ objects from the source repository into a pack in the cloned repository.
 
 --depth <depth>::
        Create a 'shallow' clone with a history truncated to the
-       specified number of revisions.
+       specified number of commits. Implies `--single-branch` unless
+       `--no-single-branch` is given to fetch the histories near the
+       tips of all branches.
 
 --[no-]single-branch::
        Clone only the history leading to the tip of a single branch,
        either specified by the `--branch` option or the primary
-       branch remote's `HEAD` points at. When creating a shallow
-       clone with the `--depth` option, this is the default, unless
-       `--no-single-branch` is given to fetch the histories near the
-       tips of all branches.
+       branch remote's `HEAD` points at.
        Further fetches into the resulting repository will only update the
        remote-tracking branch for the branch this option was used for the
        initial cloning.  If the HEAD at the remote did not point at any
index 7f34a5b33103ed1c870f234687079badc393be77..9ec6b3cc17fd776b16f6410cf88c708831d4bca3 100644 (file)
@@ -154,7 +154,11 @@ OPTIONS
 -s::
 --signoff::
        Add Signed-off-by line by the committer at the end of the commit
-       log message.
+       log message.  The meaning of a signoff depends on the project,
+       but it typically certifies that committer has
+       the rights to submit this work under the same license and
+       agrees to a Developer Certificate of Origin
+       (see http://developercertificate.org/ for more information).
 
 -n::
 --no-verify::
index c6f073cea42a2a91fba1aeb17505fe6cd7f46ac8..2e3e96f663e2ffa678f7242a661cf1f68f9c5d77 100644 (file)
@@ -92,7 +92,11 @@ refname::
        The name of the ref (the part after $GIT_DIR/).
        For a non-ambiguous short name of the ref append `:short`.
        The option core.warnAmbiguousRefs is used to select the strict
-       abbreviation mode.
+       abbreviation mode. If `strip=<N>` is appended, strips `<N>`
+       slash-separated path components from the front of the refname
+       (e.g., `%(refname:strip=2)` turns `refs/tags/foo` into `foo`.
+       `<N>` must be a positive integer.  If a displayed ref has fewer
+       components than `<N>`, the command aborts with an error.
 
 objecttype::
        The type of the object (`blob`, `tree`, `commit`, `tag`).
@@ -142,6 +146,11 @@ In addition to the above, for commit and tag objects, the header
 field names (`tree`, `parent`, `object`, `type`, and `tag`) can
 be used to specify the value in the header field.
 
+For commit and tag objects, the special `creatordate` and `creator`
+fields will correspond to the appropriate date or name-email-date tuple
+from the `committer` or `tagger` fields depending on the object type.
+These are intended for working on a mix of annotated and lightweight tags.
+
 Fields that have name-email-date tuple as its value (`author`,
 `committer`, and `tagger`) can be suffixed with `name`, `email`,
 and `date` to extract the named component.
@@ -153,8 +162,8 @@ line is 'contents:body', where body is all of the lines after the first
 blank line.  The optional GPG signature is `contents:signature`.  The
 first `N` lines of the message is obtained using `contents:lines=N`.
 
-For sorting purposes, fields with numeric values sort in numeric
-order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
+For sorting purposes, fields with numeric values sort in numeric order
+(`objectsize`, `authordate`, `committerdate`, `creatordate`, `taggerdate`).
 All other fields are used to sort in their byte-value order.
 
 There is also an option to sort by versions, this can be done by using
index e3cdaeb9586017aa86aa15fec8a13371993906e3..6821441d7d7beedac1f5b322248c3012d23bb103 100644 (file)
@@ -57,7 +57,11 @@ The names of the output files are printed to standard
 output, unless the `--stdout` option is specified.
 
 If `-o` is specified, output files are created in <dir>.  Otherwise
-they are created in the current working directory.
+they are created in the current working directory. The default path
+can be set with the 'format.outputDirectory' configuration option.
+The `-o` option takes precedence over `format.outputDirectory`.
+To store patches in the current working directory even when
+`format.outputDirectory` points elsewhere, use `-o .`.
 
 By default, the subject of a single patch is "[PATCH] " followed by
 the concatenation of lines from the commit message up to the first blank
@@ -109,6 +113,7 @@ include::diff-options.txt[]
 --signoff::
        Add `Signed-off-by:` line to the commit message, using
        the committer identity of yourself.
+       See the signoff option in linkgit:git-commit[1] for more information.
 
 --stdout::
        Print all commits to the standard output in mbox format,
index 4a44d6da13cb749759f9d6164b88974ba55485ab..cb0f6cf6782c87d7a5b08e2b75de5b4ecb2969f9 100644 (file)
@@ -23,6 +23,7 @@ SYNOPSIS
           [--break] [--heading] [-p | --show-function]
           [-A <post-context>] [-B <pre-context>] [-C <context>]
           [-W | --function-context]
+          [--threads <num>]
           [-f <file>] [-e] <pattern>
           [--and|--or|--not|(|)|-e <pattern>...]
           [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
@@ -53,9 +54,17 @@ grep.extendedRegexp::
        option is ignored when the 'grep.patternType' option is set to a value
        other than 'default'.
 
+grep.threads::
+       Number of grep worker threads to use.  If unset (or set to 0),
+       8 threads are used by default (for now).
+
 grep.fullName::
        If set to true, enable '--full-name' option by default.
 
+grep.fallbackToNoIndex::
+       If set to true, fall back to git grep --no-index if git grep
+       is executed outside of a git repository.  Defaults to false.
+
 
 OPTIONS
 -------
@@ -227,6 +236,10 @@ OPTIONS
        effectively showing the whole function in which the match was
        found.
 
+--threads <num>::
+       Number of grep worker threads to use.
+       See `grep.threads` in 'CONFIGURATION' for more information.
+
 -f <file>::
        Read patterns from <file>, one per line.
 
index 0ecd497c4de77ea2ed7afc5603b4bcbd8558d174..a77b901f1d7b5e75c66b4c1e032f35c989614cc7 100644 (file)
@@ -8,7 +8,7 @@ git-interpret-trailers - help add structured information into commit messages
 SYNOPSIS
 --------
 [verse]
-'git interpret-trailers' [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]
+'git interpret-trailers' [--in-place] [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]
 
 DESCRIPTION
 -----------
@@ -64,6 +64,9 @@ folding rules, the encoding rules and probably many other rules.
 
 OPTIONS
 -------
+--in-place::
+       Edit the files in place.
+
 --trim-empty::
        If the <value> part of any trailer contains only whitespace,
        the whole trailer will be removed from the resulting message.
@@ -216,6 +219,25 @@ Signed-off-by: Alice <alice@example.com>
 Signed-off-by: Bob <bob@example.com>
 ------------
 
+* Use the '--in-place' option to edit a message file in place:
++
+------------
+$ cat msg.txt
+subject
+
+message
+
+Signed-off-by: Bob <bob@example.com>
+$ git interpret-trailers --trailer 'Acked-by: Alice <alice@example.com>' --in-place msg.txt
+$ cat msg.txt
+subject
+
+message
+
+Signed-off-by: Bob <bob@example.com>
+Acked-by: Alice <alice@example.com>
+------------
+
 * Extract the last commit as a patch, and add a 'Cc' and a
   'Reviewed-by' trailer to it:
 +
index e26f01fb1d1aec3526879059fe6ee20438965f68..0e08f567a163571c7d8f2a4c10984691f5aba566 100644 (file)
@@ -12,6 +12,7 @@ SYNOPSIS
 'git ls-files' [-z] [-t] [-v]
                (--[cached|deleted|others|ignored|stage|unmerged|killed|modified])*
                (-[c|d|o|i|s|u|k|m])*
+               [--eol]
                [-x <pattern>|--exclude=<pattern>]
                [-X <file>|--exclude-from=<file>]
                [--exclude-per-directory=<file>]
@@ -147,6 +148,24 @@ a space) at the start of each line:
        possible for manual inspection; the exact format may change at
        any time.
 
+--eol::
+       Show <eolinfo> and <eolattr> of files.
+       <eolinfo> is the file content identification used by Git when
+       the "text" attribute is "auto" (or not set and core.autocrlf is not false).
+       <eolinfo> is either "-text", "none", "lf", "crlf", "mixed" or "".
++
+"" means the file is not a regular file, it is not in the index or
+not accessable in the working tree.
++
+<eolattr> is the attribute that is used when checking out or committing,
+it is either "", "-text", "text", "text=auto", "text eol=lf", "text eol=crlf".
+Note: Currently Git does not support "text=auto eol=lf" or "text=auto eol=crlf",
+that may change in the future.
++
+Both the <eolinfo> in the index ("i/<eolinfo>")
+and in the working tree ("w/<eolinfo>") are shown for regular files,
+followed by the  ("attr/<eolattr>").
+
 \--::
        Do not interpret any more arguments as options.
 
@@ -161,6 +180,9 @@ which case it outputs:
 
         [<tag> ]<mode> <object> <stage> <file>
 
+'git ls-files --eol' will show
+       i/<eolinfo><SPACES>w/<eolinfo><SPACES>attr/<eolattr><SPACE*><TAB><file>
+
 'git ls-files --unmerged' and 'git ls-files --stage' can be used to examine
 detailed information on unmerged paths.
 
index d510c05e11d3cbfb7fd1393331306e70bb7645db..5f2628c8f86a65b0bfe8e29995fa2176927a30f0 100644 (file)
@@ -9,8 +9,9 @@ git-ls-remote - List references in a remote repository
 SYNOPSIS
 --------
 [verse]
-'git ls-remote' [--heads] [--tags]  [--upload-pack=<exec>]
-             [--exit-code] <repository> [<refs>...]
+'git ls-remote' [--heads] [--tags] [--refs] [--upload-pack=<exec>]
+             [-q | --quiet] [--exit-code] [--get-url]
+             [--symref] [<repository> [<refs>...]]
 
 DESCRIPTION
 -----------
@@ -29,6 +30,13 @@ OPTIONS
        both, references stored in refs/heads and refs/tags are
        displayed.
 
+--refs::
+       Do not show peeled tags or pseudorefs like HEAD in the output.
+
+-q::
+--quiet::
+       Do not print remote URL to stderr.
+
 --upload-pack=<exec>::
        Specify the full path of 'git-upload-pack' on the remote
        host. This allows listing references from repositories accessed via
@@ -46,6 +54,12 @@ OPTIONS
        "url.<base>.insteadOf" config setting (See linkgit:git-config[1]) and
        exit without talking to the remote.
 
+--symref::
+       In addition to the object pointed by it, show the underlying
+       ref pointed by it when showing a symbolic ref.  Currently,
+       upload-pack only shows the symref HEAD, so it will be the only
+       one shown by ls-remote.
+
 <repository>::
        The "remote" repository to query.  This parameter can be
        either a URL or the name of a remote (see the GIT URLS and
index 93c72a29cecb7ce005dc579e79c5e5bacaaac420..a62a2a615d0e0146d538213571d7f41bd02488cf 100644 (file)
@@ -101,7 +101,7 @@ Options related to merging
 include::merge-options.txt[]
 
 -r::
---rebase[=false|true|preserve]::
+--rebase[=false|true|preserve|interactive]::
        When true, rebase the current branch on top of the upstream
        branch after fetching. If there is a remote-tracking branch
        corresponding to the upstream branch and the upstream branch
@@ -113,6 +113,8 @@ to `git rebase` so that locally created merge commits will not be flattened.
 +
 When false, merge the current branch into the upstream branch.
 +
+When `interactive`, enable the interactive mode of rebase.
++
 See `pull.rebase`, `branch.<name>.rebase` and `branch.autoSetupRebase` in
 linkgit:git-config[1] if you want to make `git pull` always use
 `--rebase` instead of merging.
index 4c775bcec48360c3a097aea9cdb765ca9a9ec100..32482cec42d3ea5661813097919ff38657c2e01c 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
-          [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose]
+          [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
           [-u | --set-upstream]
           [--[no-]signed|--sign=(true|false|if-asked)]
           [--force-with-lease[=<refname>[:<expect>]]]
index b15139ffdcda488c9e2314540885965723292a48..573616a04aec4ca5a768f0b26470489955bbf505 100644 (file)
@@ -89,6 +89,7 @@ effect to your index in a row.
 -s::
 --signoff::
        Add Signed-off-by line at the end of the commit message.
+       See the signoff option in linkgit:git-commit[1] for more information.
 
 --strategy=<strategy>::
        Use the given merge strategy.  Should only be used once.
index 7220e5eca1bddfcaf9828522c7f04ab78418874e..abab4814ec984db62dff6b493c3eb93398a36afa 100644 (file)
@@ -163,7 +163,7 @@ This option is only applicable when listing tags without annotation lines.
        A string that interpolates `%(fieldname)` from the object
        pointed at by a ref being shown.  The format is the same as
        that of linkgit:git-for-each-ref[1].  When unspecified,
-       defaults to `%(refname:short)`.
+       defaults to `%(refname:strip=2)`.
 
 --[no-]merged [<commit>]::
        Only list tags whose tips are reachable, or not reachable
index f4e5a85351d7a7fdda24ac497560f59ccdb6ef7b..c6cbed189ceddd294361502b861f37c29a8adbf1 100644 (file)
@@ -18,7 +18,7 @@ SYNOPSIS
             [--[no-]skip-worktree]
             [--ignore-submodules]
             [--[no-]split-index]
-            [--[no-|force-]untracked-cache]
+            [--[no-|test-|force-]untracked-cache]
             [--really-refresh] [--unresolve] [--again | -g]
             [--info-only] [--index-info]
             [-z] [--stdin] [--index-version <n>]
@@ -174,17 +174,30 @@ may not support it yet.
 
 --untracked-cache::
 --no-untracked-cache::
-       Enable or disable untracked cache extension. This could speed
-       up for commands that involve determining untracked files such
-       as `git status`. The underlying operating system and file
-       system must change `st_mtime` field of a directory if files
-       are added or deleted in that directory.
+       Enable or disable untracked cache feature. Please use
+       `--test-untracked-cache` before enabling it.
++
+These options take effect whatever the value of the `core.untrackedCache`
+configuration variable (see linkgit:git-config[1]). But a warning is
+emitted when the change goes against the configured value, as the
+configured value will take effect next time the index is read and this
+will remove the intended effect of the option.
+
+--test-untracked-cache::
+       Only perform tests on the working directory to make sure
+       untracked cache can be used. You have to manually enable
+       untracked cache using `--untracked-cache` or
+       `--force-untracked-cache` or the `core.untrackedCache`
+       configuration variable afterwards if you really want to use
+       it. If a test fails the exit code is 1 and a message
+       explains what is not working as needed, otherwise the exit
+       code is 0 and OK is printed.
 
 --force-untracked-cache::
-       For safety, `--untracked-cache` performs tests on the working
-       directory to make sure untracked cache can be used. These
-       tests can take a few seconds. `--force-untracked-cache` can be
-       used to skip the tests.
+       Same as `--untracked-cache`. Provided for backwards
+       compatibility with older versions of Git where
+       `--untracked-cache` used to imply `--test-untracked-cache` but
+       this option would enable the extension unconditionally.
 
 \--::
        Do not interpret any more arguments as options.
@@ -375,6 +388,37 @@ Although this bit looks similar to assume-unchanged bit, its goal is
 different from assume-unchanged bit's. Skip-worktree also takes
 precedence over assume-unchanged bit when both are set.
 
+Untracked cache
+---------------
+
+This cache is meant to speed up commands that involve determining
+untracked files such as `git status`.
+
+This feature works by recording the mtime of the working tree
+directories and then omitting reading directories and stat calls
+against files in those directories whose mtime hasn't changed. For
+this to work the underlying operating system and file system must
+change the `st_mtime` field of directories if files in the directory
+are added, modified or deleted.
+
+You can test whether the filesystem supports that with the
+`--test-untracked-cache` option. The `--untracked-cache` option used
+to implicitly perform that test in older versions of Git, but that's
+no longer the case.
+
+If you want to enable (or disable) this feature, it is easier to use
+the `core.untrackedCache` configuration variable (see
+linkgit:git-config[1]) than using the `--untracked-cache` option to
+`git update-index` in each repository, especially if you want to do so
+across all repositories you use, because you can set the configuration
+variable to `true` (or `false`) in your `$HOME/.gitconfig` just once
+and have it affect all repositories you touch.
+
+When the `core.untrackedCache` configuration variable is changed, the
+untracked cache is added to or removed from the index the next time a
+command reads the index; while when `--[no-|force-]untracked-cache`
+are used, the untracked cache is immediately added to or removed from
+the index.
 
 Configuration
 -------------
@@ -400,6 +444,9 @@ It can be useful when the inode change time is regularly modified by
 something outside Git (file system crawlers and backup systems use
 ctime for marking files processed) (see linkgit:git-config[1]).
 
+The untracked cache extension can be enabled by the
+`core.untrackedCache` configuration variable (see
+linkgit:git-config[1]).
 
 SEE ALSO
 --------
index 5b9ad0429c84d2f11b0569f6d979858c833b3768..62c76c1c8945512009c6d0ca1179cf71ec50d04e 100644 (file)
@@ -32,11 +32,9 @@ The working tree's administrative files in the repository (see
 `git worktree prune` in the main or any linked working tree to
 clean up any stale administrative files.
 
-If you move a linked working tree to another file system, or
-within a file system that does not support hard links, you need to run
-at least one git command inside the linked working tree
-(e.g. `git status`) in order to update its administrative files in the
-repository so that they do not get automatically pruned.
+If you move a linked working tree, you need to manually update the
+administrative files so that they do not get pruned automatically. See
+section "DETAILS" for more information.
 
 If a linked working tree is stored on a portable device or network share
 which is not always mounted, you can prevent its administrative files from
@@ -137,6 +135,13 @@ thumb is do not make any assumption about whether a path belongs to
 $GIT_DIR or $GIT_COMMON_DIR when you need to directly access something
 inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.
 
+If you move a linked working tree, you need to update the 'gitdir' file
+in the entry's directory. For example, if a linked working tree is moved
+to `/newpath/test-next` and its `.git` file points to
+`/path/main/.git/worktrees/test-next`, then update
+`/path/main/.git/worktrees/test-next/gitdir` to reference `/newpath/test-next`
+instead.
+
 To prevent a $GIT_DIR/worktrees entry from being pruned (which
 can be useful in some situations, such as when the
 entry's working tree is stored on a portable device), add a file named
index bff6302c0dec6d18454439c4423189a86beee396..d987ad20c90a05932733c09812324c3d176ebbbe 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.7.0/git.html[documentation for release 2.7]
+* link:v2.7.1/git.html[documentation for release 2.7.1]
 
 * release notes for
+  link:RelNotes/2.7.1.txt[2.7.1],
   link:RelNotes/2.7.0.txt[2.7].
 
 * link:v2.6.5/git.html[documentation for release 2.6.5]
index 79a1948a0bd52c778dcfccb253f9f2508b99f27e..473623d6318a859c9ed2cf600222ea6cb4a25d4c 100644 (file)
@@ -82,12 +82,12 @@ PATTERN FORMAT
 
  - An optional prefix "`!`" which negates the pattern; any
    matching file excluded by a previous pattern will become
-   included again.
+   included again. It is not possible to re-include a file if a parent
+   directory of that file is excluded. Git doesn't list excluded
+   directories for performance reasons, so any patterns on contained
+   files have no effect, no matter where they are defined.
    Put a backslash ("`\`") in front of the first "`!`" for patterns
    that begin with a literal "`!`", for example, "`\!important!.txt`".
-   It is possible to re-include a file if a parent directory of that
-   file is excluded if certain conditions are met. See section NOTES
-   for detail.
 
  - If the pattern ends with a slash, it is removed for the
    purpose of the following description, but it would only find
@@ -141,21 +141,6 @@ not tracked by Git remain untracked.
 To stop tracking a file that is currently tracked, use
 'git rm --cached'.
 
-To re-include files or directories when their parent directory is
-excluded, the following conditions must be met:
-
- - The rules to exclude a directory and re-include a subset back must
-   be in the same .gitignore file.
-
- - The directory part in the re-include rules must be literal (i.e. no
-   wildcards)
-
- - The rules to exclude the parent directory must not end with a
-   trailing slash.
-
- - The rules to exclude the parent directory must have at least one
-   slash.
-
 EXAMPLES
 --------
 
index e225974253833c97980e5ff190e291c8323757c9..cafc2843599102fae1dc070c484bc6987b84b367 100644 (file)
@@ -531,6 +531,11 @@ The most notable example is `HEAD`.
        "Secure Hash Algorithm 1"; a cryptographic hash function.
        In the context of Git used as a synonym for <<def_object_name,object name>>.
 
+[[def_shallow_clone]]shallow clone::
+       Mostly a synonym to <<def_shallow_repository,shallow repository>>
+       but the phrase makes it more explicit that it was created by
+       running `git clone --depth=...` command.
+
 [[def_shallow_repository]]shallow repository::
        A shallow <<def_repository,repository>> has an incomplete
        history some of whose <<def_commit,commits>> have <<def_parent,parents>> cauterized away (in other
index 4b659ac1a6a6c1b57d0cadc5cd69ce6b69525cc1..54b88b6dcaaa5df06fc8dad2e5f5172682269bc9 100644 (file)
@@ -43,7 +43,7 @@ people using 80-column terminals.
        commit may be copied to the output.
 
 ifndef::git-rev-list[]
---notes[=<ref>]::
+--notes[=<treeish>]::
        Show the notes (see linkgit:git-notes[1]) that annotate the
        commit, when showing the commit log message.  This is the default
        for `git log`, `git show` and `git whatchanged` commands when
@@ -54,8 +54,8 @@ By default, the notes shown are from the notes refs listed in the
 'core.notesRef' and 'notes.displayRef' variables (or corresponding
 environment overrides). See linkgit:git-config[1] for more details.
 +
-With an optional '<ref>' argument, show this notes ref instead of the
-default notes ref(s). The ref specifies the full refname when it begins
+With an optional '<treeish>' argument, use the treeish to find the notes
+to display.  The treeish can specify the full refname when it begins
 with `refs/notes/`; when it begins with `notes/`, `refs/` and otherwise
 `refs/notes/` is prefixed to form a full name of the ref.
 +
@@ -71,7 +71,7 @@ being displayed. Examples: "--notes=foo" will show only notes from
        "--notes --notes=foo --no-notes --notes=bar" will only show notes
        from "refs/notes/bar".
 
---show-notes[=<ref>]::
+--show-notes[=<treeish>]::
 --[no-]standard-notes::
        These options are deprecated. Use the above --notes/--no-notes
        options instead.
index d85e3033646faec23b23065cbd78436aca508acf..fa4bdb208cd86c603e1d7e430e753d5fe4768a13 100644 (file)
@@ -61,11 +61,11 @@ some output processing may assume ref names in UTF-8.
 '@'::
   '@' alone is a shortcut for 'HEAD'.
 
-'<refname>@\{<date>\}', e.g. 'master@\{yesterday\}', 'HEAD@\{5 minutes ago\}'::
+'<refname>@{<date>}', e.g. 'master@\{yesterday\}', 'HEAD@{5 minutes ago}'::
   A ref followed by the suffix '@' with a date specification
   enclosed in a brace
-  pair (e.g. '\{yesterday\}', '\{1 month 2 weeks 3 days 1 hour 1
-  second ago\}' or '\{1979-02-26 18:30:00\}') specifies the value
+  pair (e.g. '\{yesterday\}', '{1 month 2 weeks 3 days 1 hour 1
+  second ago}' or '{1979-02-26 18:30:00}') specifies the value
   of the ref at a prior point in time.  This suffix may only be
   used immediately following a ref name and the ref must have an
   existing log ('$GIT_DIR/logs/<ref>'). Note that this looks up the state
@@ -73,7 +73,7 @@ some output processing may assume ref names in UTF-8.
   'master' branch last week. If you want to look at commits made during
   certain times, see '--since' and '--until'.
 
-'<refname>@\{<n>\}', e.g. 'master@\{1\}'::
+'<refname>@{<n>}', e.g. 'master@\{1\}'::
   A ref followed by the suffix '@' with an ordinal specification
   enclosed in a brace pair (e.g. '\{1\}', '\{15\}') specifies
   the n-th prior value of that ref.  For example 'master@\{1\}'
@@ -82,13 +82,13 @@ some output processing may assume ref names in UTF-8.
   immediately following a ref name and the ref must have an existing
   log ('$GIT_DIR/logs/<refname>').
 
-'@\{<n>\}', e.g. '@\{1\}'::
+'@{<n>}', e.g. '@\{1\}'::
   You can use the '@' construct with an empty ref part to get at a
   reflog entry of the current branch. For example, if you are on
   branch 'blabla' then '@\{1\}' means the same as 'blabla@\{1\}'.
 
-'@\{-<n>\}', e.g. '@\{-1\}'::
-  The construct '@\{-<n>\}' means the <n>th branch/commit checked out
+'@{-<n>}', e.g. '@{-1}'::
+  The construct '@{-<n>}' means the <n>th branch/commit checked out
   before the current one.
 
 '<branchname>@\{upstream\}', e.g. 'master@\{upstream\}', '@\{u\}'::
@@ -139,7 +139,7 @@ from one location and push to another. In a non-triangular workflow,
   '<rev>{caret}1{caret}1{caret}1'.  See below for an illustration of
   the usage of this form.
 
-'<rev>{caret}\{<type>\}', e.g. 'v0.99.8{caret}\{commit\}'::
+'<rev>{caret}{<type>}', e.g. 'v0.99.8{caret}\{commit\}'::
   A suffix '{caret}' followed by an object type name enclosed in
   brace pair means dereference the object at '<rev>' recursively until
   an object of type '<type>' is found or the object cannot be
@@ -159,13 +159,13 @@ it does not have to be dereferenced even once to get to an object.
 'rev{caret}\{tag\}' can be used to ensure that 'rev' identifies an
 existing tag object.
 
-'<rev>{caret}\{\}', e.g. 'v0.99.8{caret}\{\}'::
+'<rev>{caret}{}', e.g. 'v0.99.8{caret}{}'::
   A suffix '{caret}' followed by an empty brace pair
   means the object could be a tag,
   and dereference the tag recursively until a non-tag object is
   found.
 
-'<rev>{caret}\{/<text>\}', e.g. 'HEAD^{/fix nasty bug}'::
+'<rev>{caret}{/<text>}', e.g. 'HEAD^{/fix nasty bug}'::
   A suffix '{caret}' to a revision parameter, followed by a brace
   pair that contains a text led by a slash,
   is the same as the ':/fix nasty bug' syntax below except that
index 2cfdd224a83710f32e344b76c131181527caf98c..f10941b2e816142e9659ec3982105360f79070fd 100644 (file)
@@ -51,6 +51,10 @@ struct remote
 
        The proxy to use for curl (http, https, ftp, etc.) URLs.
 
+`http_proxy_authmethod`::
+
+       The method used for authenticating against `http_proxy`.
+
 struct remotes can be found by name with remote_get(), and iterated
 through with for_each_remote(). remote_get(NULL) will return the
 default remote, given the current branch and configuration.
index 1c790ac74a6907365c4a69938c3a75ab690cfc2e..ec6bacfcdfa8418b5e24a09c04091e6b92119d46 100644 (file)
@@ -2125,8 +2125,37 @@ Allowing web browsing of a repository
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The gitweb cgi script provides users an easy way to browse your
-project's files and history without having to install Git; see the file
-gitweb/INSTALL in the Git source tree for instructions on setting it up.
+project's revisions, file contents and logs without having to install
+Git. Features like RSS/Atom feeds and blame/annotation details may
+optionally be enabled.
+
+The linkgit:git-instaweb[1] command provides a simple way to start
+browsing the repository using gitweb. The default server when using
+instaweb is lighttpd.
+
+See the file gitweb/INSTALL in the Git source tree and
+linkgit:gitweb[1] for instructions on details setting up a permament
+installation with a CGI or Perl capable server.
+
+[[how-to-get-a-git-repository-with-minimal-history]]
+How to get a Git repository with minimal history
+------------------------------------------------
+
+A <<def_shallow_clone,shallow clone>>, with its truncated
+history, is useful when one is interested only in recent history
+of a project and getting full history from the upstream is
+expensive.
+
+A <<def_shallow_clone,shallow clone>> is created by specifying
+the linkgit:git-clone[1] `--depth` switch. The depth can later be
+changed with the linkgit:git-fetch[1] `--depth` switch, or full
+history restored with `--unshallow`.
+
+Merging inside a <<def_shallow_clone,shallow clone>> will work as long
+as a merge base is in the recent history.
+Otherwise, it will be like merging unrelated histories and may
+have to result in huge conflicts.  This limitation may make such
+a repository unsuitable to be used in merge based workflows.
 
 [[sharing-development-examples]]
 Examples
@@ -4636,23 +4665,15 @@ Scan email archives for other stuff left out
 Scan man pages to see if any assume more background than this manual
 provides.
 
-Simplify beginning by suggesting disconnected head instead of
-temporary branch creation?
-
 Add more good examples.  Entire sections of just cookbook examples
 might be a good idea; maybe make an "advanced examples" section a
 standard end-of-chapter section?
 
 Include cross-references to the glossary, where appropriate.
 
-Document shallow clones?  See draft 1.5.0 release notes for some
-documentation.
-
 Add a section on working with other version control systems, including
 CVS, Subversion, and just imports of series of release tarballs.
 
-More details on gitweb?
-
 Write a chapter on using plumbing and writing scripts.
 
 Alternates, clone -reference, etc.
index 51aa9e680635e51904f0672b99018167ad1b8b5e..5873f163e51684ff4fc53119c59fe2c4fc24fabe 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.7.0
+DEF_VER=v2.7.0.GIT
 
 LF='
 '
index fd19b544c21ac4648adb8e86421ec5a8632dc0fb..fc2f1ab2c31820513758514cd445fc63521b1d19 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2025,6 +2025,7 @@ $(VCSSVN_LIB): $(VCSSVN_OBJS)
 
 export DEFAULT_EDITOR DEFAULT_PAGER
 
+.PHONY: doc man html info pdf
 doc:
        $(MAKE) -C Documentation all
 
@@ -2068,6 +2069,7 @@ po/git.pot: $(GENERATED_H) FORCE
                $(LOCALIZED_PERL)
        mv $@+ $@
 
+.PHONY: pot
 pot: po/git.pot
 
 POFILES := $(wildcard po/*.po)
@@ -2277,6 +2279,7 @@ mergetools_instdir_SQ = $(subst ','\'',$(mergetools_instdir))
 
 install_bindir_programs := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X)) $(BINDIR_PROGRAMS_NO_X)
 
+.PHONY: profile-install profile-fast-install
 profile-install: profile
        $(MAKE) install
 
@@ -2343,6 +2346,8 @@ endif
        done && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
 
+.PHONY: install-gitweb install-doc install-man install-html install-info install-pdf
+.PHONY: quick-install-doc quick-install-man quick-install-html
 install-gitweb:
        $(MAKE) -C gitweb install
 
@@ -2402,6 +2407,7 @@ rpm: dist
 
 htmldocs = git-htmldocs-$(GIT_VERSION)
 manpages = git-manpages-$(GIT_VERSION)
+.PHONY: dist-doc distclean
 dist-doc:
        $(RM) -r .doc-tmp-dir
        mkdir .doc-tmp-dir
@@ -2470,6 +2476,8 @@ ALL_COMMANDS += git
 ALL_COMMANDS += gitk
 ALL_COMMANDS += gitweb
 ALL_COMMANDS += git-gui git-citool
+
+.PHONY: check-docs
 check-docs::
        @(for v in $(ALL_COMMANDS); \
        do \
@@ -2514,6 +2522,7 @@ check-builtins::
 ### Test suite coverage testing
 #
 .PHONY: coverage coverage-clean coverage-compile coverage-test coverage-report
+.PHONY: coverage-untested-functions cover_db cover_db_html
 .PHONY: coverage-clean-results
 
 coverage:
index 3ba13ce25351c60c93d0c8ed78f207d9a591d517..7db30403c3471e15f4f15a5e68016d7926b3e3de 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.7.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.8.0.txt
\ No newline at end of file
index 42aa7aa6aa1e53e66bafd47d76b783514dcfabf1..06ec54e599586f7cfe0f08c4b63354900af33d18 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -440,7 +440,7 @@ static void read_bisect_paths(struct argv_array *array)
        if (!fp)
                die_errno("Could not open file '%s'", filename);
 
-       while (strbuf_getline(&str, fp, '\n') != EOF) {
+       while (strbuf_getline_lf(&str, fp) != EOF) {
                strbuf_trim(&str);
                if (sq_dequote_to_argv_array(str.buf, array))
                        die("Badly quoted content in file '%s': %s",
@@ -668,7 +668,7 @@ static int is_expected_rev(const struct object_id *oid)
        if (!fp)
                return 0;
 
-       if (strbuf_getline(&str, fp, '\n') != EOF)
+       if (strbuf_getline_lf(&str, fp) != EOF)
                res = !strcmp(str.buf, oid_to_hex(oid));
 
        strbuf_release(&str);
@@ -914,9 +914,9 @@ void read_bisect_terms(const char **read_bad, const char **read_good)
                                strerror(errno));
                }
        } else {
-               strbuf_getline(&str, fp, '\n');
+               strbuf_getline_lf(&str, fp);
                *read_bad = strbuf_detach(&str, NULL);
-               strbuf_getline(&str, fp, '\n');
+               strbuf_getline_lf(&str, fp);
                *read_good = strbuf_detach(&str, NULL);
        }
        strbuf_release(&str);
index 9fb42fdd714a7785f6d75486db0d48fecceaacd6..259dc1cd117ec18d37d4199873c11bbf70ad6dfb 100644 (file)
@@ -45,21 +45,6 @@ static int is_empty_file(const char *filename)
        return !st.st_size;
 }
 
-/**
- * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators.
- */
-static int strbuf_getline_crlf(struct strbuf *sb, FILE *fp)
-{
-       if (strbuf_getwholeline(sb, fp, '\n'))
-               return EOF;
-       if (sb->buf[sb->len - 1] == '\n') {
-               strbuf_setlen(sb, sb->len - 1);
-               if (sb->len > 0 && sb->buf[sb->len - 1] == '\r')
-                       strbuf_setlen(sb, sb->len - 1);
-       }
-       return 0;
-}
-
 /**
  * Returns the length of the first line of msg.
  */
@@ -284,7 +269,7 @@ static char *read_shell_var(FILE *fp, const char *key)
        struct strbuf sb = STRBUF_INIT;
        const char *str;
 
-       if (strbuf_getline(&sb, fp, '\n'))
+       if (strbuf_getline_lf(&sb, fp))
                goto fail;
 
        if (!skip_prefix(sb.buf, key, &str))
@@ -573,7 +558,7 @@ static int copy_notes_for_rebase(const struct am_state *state)
 
        fp = xfopen(am_path(state, "rewritten"), "r");
 
-       while (!strbuf_getline(&sb, fp, '\n')) {
+       while (!strbuf_getline_lf(&sb, fp)) {
                unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ];
 
                if (sb.len != GIT_SHA1_HEXSZ * 2 + 1) {
@@ -628,7 +613,7 @@ static int is_mail(FILE *fp)
        if (regcomp(&regex, header_regex, REG_NOSUB | REG_EXTENDED))
                die("invalid pattern: %s", header_regex);
 
-       while (!strbuf_getline_crlf(&sb, fp)) {
+       while (!strbuf_getline(&sb, fp)) {
                if (!sb.len)
                        break; /* End of header */
 
@@ -675,7 +660,7 @@ static int detect_patch_format(const char **paths)
 
        fp = xfopen(*paths, "r");
 
-       while (!strbuf_getline_crlf(&l1, fp)) {
+       while (!strbuf_getline(&l1, fp)) {
                if (l1.len)
                        break;
        }
@@ -696,9 +681,9 @@ static int detect_patch_format(const char **paths)
        }
 
        strbuf_reset(&l2);
-       strbuf_getline_crlf(&l2, fp);
+       strbuf_getline(&l2, fp);
        strbuf_reset(&l3);
-       strbuf_getline_crlf(&l3, fp);
+       strbuf_getline(&l3, fp);
 
        /*
         * If the second line is empty and the third is a From, Author or Date
@@ -817,7 +802,7 @@ static int stgit_patch_to_mail(FILE *out, FILE *in, int keep_cr)
        struct strbuf sb = STRBUF_INIT;
        int subject_printed = 0;
 
-       while (!strbuf_getline(&sb, in, '\n')) {
+       while (!strbuf_getline_lf(&sb, in)) {
                const char *str;
 
                if (str_isspace(sb.buf))
@@ -875,7 +860,7 @@ static int split_mail_stgit_series(struct am_state *state, const char **paths,
                return error(_("could not open '%s' for reading: %s"), *paths,
                                strerror(errno));
 
-       while (!strbuf_getline(&sb, fp, '\n')) {
+       while (!strbuf_getline_lf(&sb, fp)) {
                if (*sb.buf == '#')
                        continue; /* skip comment lines */
 
@@ -900,7 +885,7 @@ static int hg_patch_to_mail(FILE *out, FILE *in, int keep_cr)
 {
        struct strbuf sb = STRBUF_INIT;
 
-       while (!strbuf_getline(&sb, in, '\n')) {
+       while (!strbuf_getline_lf(&sb, in)) {
                const char *str;
 
                if (skip_prefix(sb.buf, "# User ", &str))
@@ -1317,7 +1302,7 @@ static int parse_mail(struct am_state *state, const char *mail)
 
        /* Extract message and author information */
        fp = xfopen(am_path(state, "info"), "r");
-       while (!strbuf_getline(&sb, fp, '\n')) {
+       while (!strbuf_getline_lf(&sb, fp)) {
                const char *x;
 
                if (skip_prefix(sb.buf, "Subject: ", &x)) {
@@ -1383,7 +1368,7 @@ static int get_mail_commit_sha1(unsigned char *commit_id, const char *mail)
        FILE *fp = xfopen(mail, "r");
        const char *x;
 
-       if (strbuf_getline(&sb, fp, '\n'))
+       if (strbuf_getline_lf(&sb, fp))
                return -1;
 
        if (!skip_prefix(sb.buf, "From ", &x))
@@ -1657,7 +1642,7 @@ static int fall_back_threeway(const struct am_state *state, const char *index_pa
 
                init_revisions(&rev_info, NULL);
                rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;
-               diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1);
+               diff_opt_parse(&rev_info.diffopt, &diff_filter_str, 1, rev_info.prefix);
                add_pending_sha1(&rev_info, "HEAD", our_tree, 0);
                diff_setup_done(&rev_info.diffopt);
                run_diff_index(&rev_info, 1);
@@ -1939,6 +1924,7 @@ static void am_run(struct am_state *state, int resume)
         */
        if (!state->rebasing) {
                am_destroy(state);
+               close_all_packs();
                run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
        }
 }
index 1df13cf7f4b501ed82dcbffdf4620706591a245e..55bf5fae9d5d6ea6c4e058e50d9353e77e09b34b 100644 (file)
@@ -28,6 +28,7 @@
 #include "line-range.h"
 #include "line-log.h"
 #include "dir.h"
+#include "progress.h"
 
 static char blame_usage[] = N_("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>");
 
@@ -50,6 +51,7 @@ static int incremental;
 static int xdl_opts;
 static int abbrev = -1;
 static int no_whole_file_rename;
+static int show_progress;
 
 static struct date_mode blame_date_mode = { DATE_ISO8601 };
 static size_t blame_date_width;
@@ -127,6 +129,11 @@ struct origin {
        char path[FLEX_ARRAY];
 };
 
+struct progress_info {
+       struct progress *progress;
+       int blamed_lines;
+};
+
 static int diff_hunks(mmfile_t *file_a, mmfile_t *file_b, long ctxlen,
                      xdl_emit_hunk_consume_func_t hunk_func, void *cb_data)
 {
@@ -1746,7 +1753,8 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
  * The blame_entry is found to be guilty for the range.
  * Show it in incremental output.
  */
-static void found_guilty_entry(struct blame_entry *ent)
+static void found_guilty_entry(struct blame_entry *ent,
+                          struct progress_info *pi)
 {
        if (incremental) {
                struct origin *suspect = ent->suspect;
@@ -1758,6 +1766,8 @@ static void found_guilty_entry(struct blame_entry *ent)
                write_filename_info(suspect->path);
                maybe_flush_or_die(stdout, "stdout");
        }
+       pi->blamed_lines += ent->num_lines;
+       display_progress(pi->progress, pi->blamed_lines);
 }
 
 /*
@@ -1768,6 +1778,11 @@ static void assign_blame(struct scoreboard *sb, int opt)
 {
        struct rev_info *revs = sb->revs;
        struct commit *commit = prio_queue_get(&sb->commits);
+       struct progress_info pi = { NULL, 0 };
+
+       if (show_progress)
+               pi.progress = start_progress_delay(_("Blaming lines"),
+                                                  sb->num_lines, 50, 1);
 
        while (commit) {
                struct blame_entry *ent;
@@ -1809,7 +1824,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
                        suspect->guilty = 1;
                        for (;;) {
                                struct blame_entry *next = ent->next;
-                               found_guilty_entry(ent);
+                               found_guilty_entry(ent, &pi);
                                if (next) {
                                        ent = next;
                                        continue;
@@ -1825,6 +1840,8 @@ static void assign_blame(struct scoreboard *sb, int opt)
                if (DEBUG) /* sanity */
                        sanity_check_refcnt(sb);
        }
+
+       stop_progress(&pi.progress);
 }
 
 static const char *format_time(unsigned long time, const char *tz_str,
@@ -2392,11 +2409,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
        ce->ce_mode = create_ce_mode(mode);
        add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
 
-       /*
-        * We are not going to write this out, so this does not matter
-        * right now, but someday we might optimize diff-index --cached
-        * with cache-tree information.
-        */
        cache_tree_invalidate_path(&the_index, path);
 
        return commit;
@@ -2520,6 +2532,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
                OPT_BOOL('b', NULL, &blank_boundary, N_("Show blank SHA-1 for boundary commits (Default: off)")),
                OPT_BOOL(0, "root", &show_root, N_("Do not treat root commits as boundaries (Default: off)")),
                OPT_BOOL(0, "show-stats", &show_stats, N_("Show work cost statistics")),
+               OPT_BOOL(0, "progress", &show_progress, N_("Force progress reporting")),
                OPT_BIT(0, "score-debug", &output_option, N_("Show output score for blame entries"), OUTPUT_SHOW_SCORE),
                OPT_BIT('f', "show-name", &output_option, N_("Show original filename (Default: auto)"), OUTPUT_SHOW_NAME),
                OPT_BIT('n', "show-number", &output_option, N_("Show original linenumber (Default: off)"), OUTPUT_SHOW_NUMBER),
@@ -2555,6 +2568,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 
        save_commit_buffer = 0;
        dashdash_pos = 0;
+       show_progress = -1;
 
        parse_options_start(&ctx, argc, argv, prefix, options,
                            PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0);
@@ -2579,6 +2593,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        DIFF_OPT_CLR(&revs.diffopt, FOLLOW_RENAMES);
        argc = parse_options_end(&ctx);
 
+       if (incremental || (output_option & OUTPUT_PORCELAIN)) {
+               if (show_progress > 0)
+                       die("--progress can't be used with --incremental or porcelain formats");
+               show_progress = 0;
+       } else if (show_progress < 0)
+               show_progress = isatty(2);
+
        if (0 < abbrev)
                /* one more abbrev length is needed for the boundary commit */
                abbrev++;
@@ -2828,11 +2849,11 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
 
        read_mailmap(&mailmap, NULL);
 
+       assign_blame(&sb, opt);
+
        if (!incremental)
                setup_pager();
 
-       assign_blame(&sb, opt);
-
        free(final_commit_name);
 
        if (incremental)
index c0fd8dbb1c1bed55f541569e0c13cc865c39ec4f..54db1184a003897294b6aaa46bc6bf29faa919bc 100644 (file)
@@ -401,7 +401,7 @@ static int batch_objects(struct batch_options *opt)
        save_warning = warn_on_object_refname_ambiguity;
        warn_on_object_refname_ambiguity = 0;
 
-       while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+       while (strbuf_getline(&buf, stdin) != EOF) {
                if (data.split_on_whitespace) {
                        /*
                         * Split at first whitespace, tying off the beginning
index 265c9ba02264d29eb3f63f1a8264c9fe7e642332..087325ef6954e4a2364d194f8d7ac27fedb7fc67 100644 (file)
@@ -73,12 +73,13 @@ static void check_attr_stdin_paths(const char *prefix, int cnt,
        struct git_attr_check *check)
 {
        struct strbuf buf, nbuf;
-       int line_termination = nul_term_line ? 0 : '\n';
+       strbuf_getline_fn getline_fn;
 
+       getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
        strbuf_init(&buf, 0);
        strbuf_init(&nbuf, 0);
-       while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
-               if (line_termination && buf.buf[0] == '"') {
+       while (getline_fn(&buf, stdin) != EOF) {
+               if (!nul_term_line && buf.buf[0] == '"') {
                        strbuf_reset(&nbuf);
                        if (unquote_c_style(&nbuf, buf.buf, NULL))
                                die("line is badly quoted");
index 43f361797ac73b64c79bb163cbb38baf78981fc9..4f0b09e2db5c0e0bc4665b06dc543b7f8ea1d467 100644 (file)
@@ -117,13 +117,14 @@ static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix)
 {
        struct strbuf buf, nbuf;
        char *pathspec[2] = { NULL, NULL };
-       int line_termination = nul_term_line ? 0 : '\n';
+       strbuf_getline_fn getline_fn;
        int num_ignored = 0;
 
+       getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
        strbuf_init(&buf, 0);
        strbuf_init(&nbuf, 0);
-       while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
-               if (line_termination && buf.buf[0] == '"') {
+       while (getline_fn(&buf, stdin) != EOF) {
+               if (!nul_term_line && buf.buf[0] == '"') {
                        strbuf_reset(&nbuf);
                        if (unquote_c_style(&nbuf, buf.buf, NULL))
                                die("line is badly quoted");
index eaaea546d30871ad7442456f7eec4ae849f68374..cf0f54f6b92ec8db45158c43ad164413ec4a1333 100644 (file)
@@ -54,7 +54,7 @@ int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
 
        if (use_stdin) {
                struct strbuf buf = STRBUF_INIT;
-               while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+               while (strbuf_getline_lf(&buf, stdin) != EOF) {
                        check_mailmap(&mailmap, buf.buf);
                        maybe_flush_or_die(stdout, "stdout");
                }
index 8028c3768f3ef09035ba9092b4e34cdb498405e9..ed888a5b9e8a2978369c404ab050b237ab5c7b4d 100644 (file)
@@ -11,7 +11,7 @@
 #include "parse-options.h"
 
 #define CHECKOUT_ALL 4
-static int line_termination = '\n';
+static int nul_term_line;
 static int checkout_stage; /* default to checkout stage0 */
 static int to_tempfile;
 static char topath[4][TEMPORARY_FILENAME_LENGTH + 1];
@@ -35,7 +35,8 @@ static void write_tempfile_record(const char *name, const char *prefix)
                fputs(topath[checkout_stage], stdout);
 
        putchar('\t');
-       write_name_quoted_relative(name, prefix, stdout, line_termination);
+       write_name_quoted_relative(name, prefix, stdout,
+                                  nul_term_line ? '\0' : '\n');
 
        for (i = 0; i < 4; i++) {
                topath[i][0] = 0;
@@ -144,10 +145,7 @@ static int option_parse_u(const struct option *opt,
 static int option_parse_z(const struct option *opt,
                          const char *arg, int unset)
 {
-       if (unset)
-               line_termination = '\n';
-       else
-               line_termination = 0;
+       nul_term_line = !unset;
        return 0;
 }
 
@@ -254,13 +252,15 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
 
        if (read_from_stdin) {
                struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
+               strbuf_getline_fn getline_fn;
 
                if (all)
                        die("git checkout-index: don't mix '--all' and '--stdin'");
 
-               while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
+               getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
+               while (getline_fn(&buf, stdin) != EOF) {
                        char *p;
-                       if (line_termination && buf.buf[0] == '"') {
+                       if (!nul_term_line && buf.buf[0] == '"') {
                                strbuf_reset(&nbuf);
                                if (unquote_c_style(&nbuf, buf.buf, NULL))
                                        die("line is badly quoted");
index e8110a9243f648129ffbea0de2af039ad7791aa1..5af84a3118d20da437d3e08c1667f76dc2f57845 100644 (file)
@@ -661,7 +661,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
                        describe_detached_head(_("HEAD is now at"), new->commit);
                }
        } else if (new->path) { /* Switch branches. */
-               create_symref("HEAD", new->path, msg.buf);
+               if (create_symref("HEAD", new->path, msg.buf) < 0)
+                       die("unable to update HEAD");
                if (!opts->quiet) {
                        if (old->path && !strcmp(new->path, old->path)) {
                                if (opts->new_branch_force)
index d7acb94a9594563b1473ecac29bd5de9a5e8a55a..7b08237480fde101640ce361b3b95106e7ffa930 100644 (file)
@@ -147,30 +147,6 @@ static int exclude_cb(const struct option *opt, const char *arg, int unset)
        return 0;
 }
 
-/*
- * Return 1 if the given path is the root of a git repository or
- * submodule else 0. Will not return 1 for bare repositories with the
- * exception of creating a bare repository in "foo/.git" and calling
- * is_git_repository("foo").
- */
-static int is_git_repository(struct strbuf *path)
-{
-       int ret = 0;
-       int gitfile_error;
-       size_t orig_path_len = path->len;
-       assert(orig_path_len != 0);
-       strbuf_complete(path, '/');
-       strbuf_addstr(path, ".git");
-       if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf))
-               ret = 1;
-       if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED ||
-           gitfile_error == READ_GITFILE_ERR_READ_FAILED)
-               ret = 1;  /* This could be a real .git file, take the
-                          * safe option and avoid cleaning */
-       strbuf_setlen(path, orig_path_len);
-       return ret;
-}
-
 static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
                int dry_run, int quiet, int *dir_gone)
 {
@@ -182,7 +158,7 @@ static int remove_dirs(struct strbuf *path, const char *prefix, int force_flag,
 
        *dir_gone = 1;
 
-       if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_git_repository(path)) {
+       if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) && is_nonbare_repository_dir(path)) {
                if (!quiet) {
                        quote_path_relative(path->buf, prefix, &quoted);
                        printf(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
@@ -594,7 +570,7 @@ static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
                               clean_get_color(CLEAN_COLOR_RESET));
                }
 
-               if (strbuf_getline(&choice, stdin, '\n') != EOF) {
+               if (strbuf_getline_lf(&choice, stdin) != EOF) {
                        strbuf_trim(&choice);
                } else {
                        eof = 1;
@@ -676,7 +652,7 @@ static int filter_by_patterns_cmd(void)
                clean_print_color(CLEAN_COLOR_PROMPT);
                printf(_("Input ignore patterns>> "));
                clean_print_color(CLEAN_COLOR_RESET);
-               if (strbuf_getline(&confirm, stdin, '\n') != EOF)
+               if (strbuf_getline_lf(&confirm, stdin) != EOF)
                        strbuf_trim(&confirm);
                else
                        putchar('\n');
@@ -774,7 +750,7 @@ static int ask_each_cmd(void)
                        qname = quote_path_relative(item->string, NULL, &buf);
                        /* TRANSLATORS: Make sure to keep [y/N] as is */
                        printf(_("Remove %s [y/N]? "), qname);
-                       if (strbuf_getline(&confirm, stdin, '\n') != EOF) {
+                       if (strbuf_getline_lf(&confirm, stdin) != EOF) {
                                strbuf_trim(&confirm);
                        } else {
                                putchar('\n');
index a0b3cd9e5617b5a3a45dd01c8a2c7af0b2fd9668..bcba0805e1c9c5691c2e876f9748a2cf492b1c70 100644 (file)
@@ -339,7 +339,7 @@ static void copy_alternates(struct strbuf *src, struct strbuf *dst,
        FILE *in = fopen(src->buf, "r");
        struct strbuf line = STRBUF_INIT;
 
-       while (strbuf_getline(&line, in, '\n') != EOF) {
+       while (strbuf_getline(&line, in) != EOF) {
                char *abs_path;
                if (!line.len || line.buf[0] == '#')
                        continue;
@@ -636,9 +636,11 @@ static void update_remote_refs(const struct ref *refs,
                struct strbuf head_ref = STRBUF_INIT;
                strbuf_addstr(&head_ref, branch_top);
                strbuf_addstr(&head_ref, "HEAD");
-               create_symref(head_ref.buf,
-                             remote_head_points_at->peer_ref->name,
-                             msg);
+               if (create_symref(head_ref.buf,
+                                 remote_head_points_at->peer_ref->name,
+                                 msg) < 0)
+                       die("unable to update %s", head_ref.buf);
+               strbuf_release(&head_ref);
        }
 }
 
@@ -648,7 +650,8 @@ static void update_head(const struct ref *our, const struct ref *remote,
        const char *head;
        if (our && skip_prefix(our->name, "refs/heads/", &head)) {
                /* Local default branch link */
-               create_symref("HEAD", our->name, NULL);
+               if (create_symref("HEAD", our->name, NULL) < 0)
+                       die("unable to update HEAD");
                if (!option_bare) {
                        update_ref(msg, "HEAD", our->old_oid.hash, NULL, 0,
                                   UPDATE_REFS_DIE_ON_ERR);
index 449413c8a873ebcfa2ceaccae6b89a3f1245c117..33314b4d7127cb6e4116c350e113058e07f58474 100644 (file)
@@ -51,7 +51,7 @@ int cmd_column(int argc, const char **argv, const char *prefix)
                        die(_("--command must be the first argument"));
        }
        finalize_colopts(&colopts, -1);
-       while (!strbuf_getline(&sb, stdin, '\n'))
+       while (!strbuf_getline(&sb, stdin))
                string_list_append(&list, sb.buf);
 
        print_columns(&list, colopts, &copts);
index d054f849606b248a82f7b29103308feab36ca9e9..b3bd2d41813f80d848afc199c2fae92cae6b6c11 100644 (file)
@@ -761,7 +761,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
                hook_arg2 = "";
        }
 
-       s->fp = fopen(git_path(commit_editmsg), "w");
+       s->fp = fopen_for_writing(git_path(commit_editmsg));
        if (s->fp == NULL)
                die_errno(_("could not open '%s'"), git_path(commit_editmsg));
 
@@ -1690,7 +1690,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                if (fp == NULL)
                        die_errno(_("could not open '%s' for reading"),
                                  git_path_merge_head());
-               while (strbuf_getline(&m, fp, '\n') != EOF) {
+               while (strbuf_getline_lf(&m, fp) != EOF) {
                        struct commit *parent;
 
                        parent = get_merge_parent(m.buf);
index ed0acca91fb870d3f773779b34f4e24c401945e5..52c98a9217c60a60f0012dbdafbb193e78ec8a33 100644 (file)
@@ -341,7 +341,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
        }
        if (no_index)
                /* If this is a no-index diff, just run it and exit there. */
-               diff_no_index(&rev, argc, argv, prefix);
+               diff_no_index(&rev, argc, argv);
 
        /* Otherwise, we are doing the usual "git" diff */
        rev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;
index d9ac5d8410b30e02fbb8edb06a1991655c5be8f4..2471297f7101964c61c055b10e24a7aa4b65326a 100644 (file)
@@ -880,7 +880,7 @@ static void export_marks(char *file)
        FILE *f;
        int e = 0;
 
-       f = fopen(file, "w");
+       f = fopen_for_writing(file);
        if (!f)
                die_errno("Unable to open marks file %s for writing.", file);
 
index cf3019e05bdf45e1fa16a483621a6773976f98c5..9b2a514e1d787784c2fac8d844d58013b6091aa6 100644 (file)
@@ -158,7 +158,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
                else {
                        /* read from stdin one ref per line, until EOF */
                        struct strbuf line = STRBUF_INIT;
-                       while (strbuf_getline(&line, stdin, '\n') != EOF)
+                       while (strbuf_getline_lf(&line, stdin) != EOF)
                                add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf);
                        strbuf_release(&line);
                }
index c85f3471d4b53ce7db7662b5531ddebe5513b7b0..8e742135f049c2792bfc5a20299dac88518929cc 100644 (file)
@@ -37,6 +37,7 @@ static int prune = -1; /* unspecified */
 static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
 static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow;
+static int max_children = 1;
 static const char *depth;
 static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
@@ -99,6 +100,8 @@ static struct option builtin_fetch_options[] = {
                    N_("fetch all tags and associated objects"), TAGS_SET),
        OPT_SET_INT('n', NULL, &tags,
                    N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
+       OPT_INTEGER('j', "jobs", &max_children,
+                   N_("number of submodules fetched in parallel")),
        OPT_BOOL('p', "prune", &prune,
                 N_("prune remote-tracking branches no longer on remote")),
        { OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
@@ -837,7 +840,7 @@ static void check_not_current_branch(struct ref *ref_map)
 static int truncate_fetch_head(void)
 {
        const char *filename = git_path_fetch_head();
-       FILE *fp = fopen(filename, "w");
+       FILE *fp = fopen_for_writing(filename);
 
        if (!fp)
                return error(_("cannot open %s: %s\n"), filename, strerror(errno));
@@ -1213,7 +1216,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
                result = fetch_populated_submodules(&options,
                                                    submodule_prefix,
                                                    recurse_submodules,
-                                                   verbosity < 0);
+                                                   verbosity < 0,
+                                                   max_children);
                argv_array_clear(&options);
        }
 
@@ -1221,6 +1225,8 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        list.strdup_strings = 1;
        string_list_clear(&list, 0);
 
+       close_all_packs();
+
        argv_array_pushl(&argv_gc_auto, "gc", "--auto", NULL);
        if (verbosity < 0)
                argv_array_push(&argv_gc_auto, "--quiet");
index 4229cae390ddddcc74f3506dc892ed02b45d7eae..8c516a95438e5aa997049da24160764ff4ca985c 100644 (file)
@@ -24,11 +24,11 @@ static char const * const grep_usage[] = {
        NULL
 };
 
-static int use_threads = 1;
+#define GREP_NUM_THREADS_DEFAULT 8
+static int num_threads;
 
 #ifndef NO_PTHREADS
-#define THREADS 8
-static pthread_t threads[THREADS];
+static pthread_t *threads;
 
 /* We use one producer thread and THREADS consumer
  * threads. The producer adds struct work_items to 'todo' and the
@@ -63,13 +63,13 @@ static pthread_mutex_t grep_mutex;
 
 static inline void grep_lock(void)
 {
-       if (use_threads)
+       if (num_threads)
                pthread_mutex_lock(&grep_mutex);
 }
 
 static inline void grep_unlock(void)
 {
-       if (use_threads)
+       if (num_threads)
                pthread_mutex_unlock(&grep_mutex);
 }
 
@@ -206,7 +206,8 @@ static void start_threads(struct grep_opt *opt)
                strbuf_init(&todo[i].out, 0);
        }
 
-       for (i = 0; i < ARRAY_SIZE(threads); i++) {
+       threads = xcalloc(num_threads, sizeof(*threads));
+       for (i = 0; i < num_threads; i++) {
                int err;
                struct grep_opt *o = grep_opt_dup(opt);
                o->output = strbuf_out;
@@ -238,12 +239,14 @@ static int wait_all(void)
        pthread_cond_broadcast(&cond_add);
        grep_unlock();
 
-       for (i = 0; i < ARRAY_SIZE(threads); i++) {
+       for (i = 0; i < num_threads; i++) {
                void *h;
                pthread_join(threads[i], &h);
                hit |= (int) (intptr_t) h;
        }
 
+       free(threads);
+
        pthread_mutex_destroy(&grep_mutex);
        pthread_mutex_destroy(&grep_read_mutex);
        pthread_mutex_destroy(&grep_attr_mutex);
@@ -267,6 +270,14 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
        int st = grep_config(var, value, cb);
        if (git_color_default_config(var, value, cb) < 0)
                st = -1;
+
+       if (!strcmp(var, "grep.threads")) {
+               num_threads = git_config_int(var, value);
+               if (num_threads < 0)
+                       die(_("invalid number of threads specified (%d) for %s"),
+                           num_threads, var);
+       }
+
        return st;
 }
 
@@ -294,7 +305,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
        }
 
 #ifndef NO_PTHREADS
-       if (use_threads) {
+       if (num_threads) {
                add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
                strbuf_release(&pathbuf);
                return 0;
@@ -323,7 +334,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
                strbuf_addstr(&buf, filename);
 
 #ifndef NO_PTHREADS
-       if (use_threads) {
+       if (num_threads) {
                add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
                strbuf_release(&buf);
                return 0;
@@ -375,7 +386,7 @@ static int grep_cache(struct grep_opt *opt, const struct pathspec *pathspec, int
 
        for (nr = 0; nr < active_nr; nr++) {
                const struct cache_entry *ce = active_cache[nr];
-               if (!S_ISREG(ce->ce_mode))
+               if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce))
                        continue;
                if (!ce_path_match(ce, pathspec, NULL))
                        continue;
@@ -562,7 +573,7 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
        patterns = from_stdin ? stdin : fopen(arg, "r");
        if (!patterns)
                die_errno(_("cannot open '%s'"), arg);
-       while (strbuf_getline(&sb, patterns, '\n') == 0) {
+       while (strbuf_getline(&sb, patterns) == 0) {
                /* ignore empty line like grep does */
                if (sb.len == 0)
                        continue;
@@ -697,6 +708,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                        N_("show <n> context lines before matches")),
                OPT_INTEGER('A', "after-context", &opt.post_context,
                        N_("show <n> context lines after matches")),
+               OPT_INTEGER(0, "threads", &num_threads,
+                       N_("use <n> worker threads")),
                OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
                        context_callback),
                OPT_BOOL('p', "show-function", &opt.funcname,
@@ -755,9 +768,15 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                             PARSE_OPT_STOP_AT_NON_OPTION);
        grep_commit_pattern_type(pattern_type_arg, &opt);
 
-       if (use_index && !startup_info->have_repository)
-               /* die the same way as if we did it at the beginning */
-               setup_git_directory();
+       if (use_index && !startup_info->have_repository) {
+               int fallback = 0;
+               git_config_get_bool("grep.fallbacktonoindex", &fallback);
+               if (fallback)
+                       use_index = 0;
+               else
+                       /* die the same way as if we did it at the beginning */
+                       setup_git_directory();
+       }
 
        /*
         * skip a -- separator; we know it cannot be
@@ -786,7 +805,6 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                opt.output_priv = &path_list;
                opt.output = append_path;
                string_list_append(&path_list, show_in_pager);
-               use_threads = 0;
        }
 
        if (!opt.pattern_list)
@@ -817,14 +835,18 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
        }
 
 #ifndef NO_PTHREADS
-       if (list.nr || cached || online_cpus() == 1)
-               use_threads = 0;
+       if (list.nr || cached || show_in_pager)
+               num_threads = 0;
+       else if (num_threads == 0)
+               num_threads = GREP_NUM_THREADS_DEFAULT;
+       else if (num_threads < 0)
+               die(_("invalid number of threads specified (%d)"), num_threads);
 #else
-       use_threads = 0;
+       num_threads = 0;
 #endif
 
 #ifndef NO_PTHREADS
-       if (use_threads) {
+       if (num_threads) {
                if (!(opt.name_only || opt.unmatch_name_only || opt.count)
                    && (opt.pre_context || opt.post_context ||
                        opt.file_break || opt.funcbody))
@@ -894,7 +916,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
                hit = grep_objects(&opt, &pathspec, &list);
        }
 
-       if (use_threads)
+       if (num_threads)
                hit |= wait_all();
        if (hit && show_in_pager)
                run_pager(&opt, prefix);
index 43b098b76c0db28a93c6b1ebf1ea1131b0d67a0b..ff20395c69780cb5869300af83084d6cac1bbd4d 100644 (file)
@@ -60,7 +60,7 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
 {
        struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
 
-       while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+       while (strbuf_getline(&buf, stdin) != EOF) {
                if (buf.buf[0] == '"') {
                        strbuf_reset(&nbuf);
                        if (unquote_c_style(&nbuf, buf.buf, NULL))
index 46838d24a90a7dff11624902281fd72ce6409756..b99ae4be8875ad8fb41fd8be2a84b6191681a4e4 100644 (file)
 #include "trailer.h"
 
 static const char * const git_interpret_trailers_usage[] = {
-       N_("git interpret-trailers [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"),
+       N_("git interpret-trailers [--in-place] [--trim-empty] [(--trailer <token>[(=|:)<value>])...] [<file>...]"),
        NULL
 };
 
 int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
 {
+       int in_place = 0;
        int trim_empty = 0;
        struct string_list trailers = STRING_LIST_INIT_DUP;
 
        struct option options[] = {
+               OPT_BOOL(0, "in-place", &in_place, N_("edit files in place")),
                OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty trailers")),
                OPT_STRING_LIST(0, "trailer", &trailers, N_("trailer"),
                                N_("trailer(s) to add")),
@@ -34,9 +36,12 @@ int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
        if (argc) {
                int i;
                for (i = 0; i < argc; i++)
-                       process_trailers(argv[i], trim_empty, &trailers);
-       } else
-               process_trailers(NULL, trim_empty, &trailers);
+                       process_trailers(argv[i], in_place, trim_empty, &trailers);
+       } else {
+               if (in_place)
+                       die(_("no input file given for in-place editing"));
+               process_trailers(NULL, in_place, trim_empty, &trailers);
+       }
 
        string_list_clear(&trailers, 0);
 
index e00cea75cca8bbde28ba45359c28b5a13a1b75e7..0d738d6ddc0d6335e15392dd90e4118e2cb58b88 100644 (file)
@@ -699,6 +699,7 @@ static int do_signoff;
 static const char *signature = git_version_string;
 static const char *signature_file;
 static int config_cover_letter;
+static const char *config_output_directory;
 
 enum {
        COVER_UNSET,
@@ -777,6 +778,8 @@ static int git_format_config(const char *var, const char *value, void *cb)
                config_cover_letter = git_config_bool(var, value) ? COVER_ON : COVER_OFF;
                return 0;
        }
+       if (!strcmp(var, "format.outputdirectory"))
+               return git_config_string(&config_output_directory, var, value);
 
        return git_log_config(var, value, cb);
 }
@@ -1391,6 +1394,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        if (rev.show_notes)
                init_display_notes(&rev.notes_opt);
 
+       if (!output_directory && !use_stdout)
+               output_directory = config_output_directory;
+
        if (!use_stdout)
                output_directory = set_outdir(prefix, output_directory);
        else
index b6a7cb0c7c48293c6348806cb342a9289f146740..dedf02dc702d1cc94399f45869e5d01d2f0eecb9 100644 (file)
@@ -27,6 +27,7 @@ static int show_killed;
 static int show_valid_bit;
 static int line_terminator = '\n';
 static int debug_mode;
+static int show_eol;
 
 static const char *prefix;
 static int max_prefix_len;
@@ -47,6 +48,23 @@ static const char *tag_modified = "";
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
+static void write_eolinfo(const struct cache_entry *ce, const char *path)
+{
+       if (!show_eol)
+               return;
+       else {
+               struct stat st;
+               const char *i_txt = "";
+               const char *w_txt = "";
+               const char *a_txt = get_convert_attr_ascii(path);
+               if (ce && S_ISREG(ce->ce_mode))
+                       i_txt = get_cached_convert_stats_ascii(ce->name);
+               if (!lstat(path, &st) && S_ISREG(st.st_mode))
+                       w_txt = get_wt_convert_stats_ascii(path);
+               printf("i/%-5s w/%-5s attr/%-17s\t", i_txt, w_txt, a_txt);
+       }
+}
+
 static void write_name(const char *name)
 {
        /*
@@ -68,6 +86,7 @@ static void show_dir_entry(const char *tag, struct dir_entry *ent)
                return;
 
        fputs(tag, stdout);
+       write_eolinfo(NULL, ent->name);
        write_name(ent->name);
 }
 
@@ -170,6 +189,7 @@ static void show_ce_entry(const char *tag, const struct cache_entry *ce)
                       find_unique_abbrev(ce->sha1,abbrev),
                       ce_stage(ce));
        }
+       write_eolinfo(ce, ce->name);
        write_name(ce->name);
        if (debug_mode) {
                const struct stat_data *sd = &ce->ce_stat_data;
@@ -433,6 +453,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
                OPT_BIT(0, "directory", &dir.flags,
                        N_("show 'other' directories' names only"),
                        DIR_SHOW_OTHER_DIRECTORIES),
+               OPT_BOOL(0, "eol", &show_eol, N_("show line endings of files")),
                OPT_NEGBIT(0, "empty-directory", &dir.flags,
                        N_("don't show empty directories"),
                        DIR_HIDE_EMPTY_DIRECTORIES),
index fa65a8448aadcb2d26613867cab7822e02e4853c..66cdd45cc10afd37f93f260688700408d11b1f5f 100644 (file)
@@ -3,9 +3,12 @@
 #include "transport.h"
 #include "remote.h"
 
-static const char ls_remote_usage[] =
-"git ls-remote [--heads] [--tags]  [--upload-pack=<exec>]\n"
-"                     [-q | --quiet] [--exit-code] [--get-url] [<repository> [<refs>...]]";
+static const char * const ls_remote_usage[] = {
+       N_("git ls-remote [--heads] [--tags] [--refs] [--upload-pack=<exec>]\n"
+          "                     [-q | --quiet] [--exit-code] [--get-url]\n"
+          "                     [--symref] [<repository> [<refs>...]]"),
+       NULL
+};
 
 /*
  * Is there one among the list of patterns that match the tail part
@@ -30,12 +33,12 @@ static int tail_match(const char **pattern, const char *path)
 
 int cmd_ls_remote(int argc, const char **argv, const char *prefix)
 {
-       int i;
        const char *dest = NULL;
        unsigned flags = 0;
        int get_url = 0;
        int quiet = 0;
        int status = 0;
+       int show_symref_target = 0;
        const char *uploadpack = NULL;
        const char **pattern = NULL;
 
@@ -43,59 +46,36 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
        struct transport *transport;
        const struct ref *ref;
 
-       if (argc == 2 && !strcmp("-h", argv[1]))
-               usage(ls_remote_usage);
+       struct option options[] = {
+               OPT__QUIET(&quiet, N_("do not print remote URL")),
+               OPT_STRING(0, "upload-pack", &uploadpack, N_("exec"),
+                          N_("path of git-upload-pack on the remote host")),
+               { OPTION_STRING, 0, "exec", &uploadpack, N_("exec"),
+                          N_("path of git-upload-pack on the remote host"),
+                          PARSE_OPT_HIDDEN },
+               OPT_BIT('t', "tags", &flags, N_("limit to tags"), REF_TAGS),
+               OPT_BIT('h', "heads", &flags, N_("limit to heads"), REF_HEADS),
+               OPT_BIT(0, "refs", &flags, N_("do not show peeled tags"), REF_NORMAL),
+               OPT_BOOL(0, "get-url", &get_url,
+                        N_("take url.<base>.insteadOf into account")),
+               OPT_SET_INT(0, "exit-code", &status,
+                           N_("exit with exit code 2 if no matching refs are found"), 2),
+               OPT_BOOL(0, "symref", &show_symref_target,
+                        N_("show underlying ref in addition to the object pointed by it")),
+               OPT_END()
+       };
 
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
+       argc = parse_options(argc, argv, prefix, options, ls_remote_usage,
+                            PARSE_OPT_STOP_AT_NON_OPTION);
+       dest = argv[0];
 
-               if (*arg == '-') {
-                       if (starts_with(arg, "--upload-pack=")) {
-                               uploadpack = arg + 14;
-                               continue;
-                       }
-                       if (starts_with(arg, "--exec=")) {
-                               uploadpack = arg + 7;
-                               continue;
-                       }
-                       if (!strcmp("--tags", arg) || !strcmp("-t", arg)) {
-                               flags |= REF_TAGS;
-                               continue;
-                       }
-                       if (!strcmp("--heads", arg) || !strcmp("-h", arg)) {
-                               flags |= REF_HEADS;
-                               continue;
-                       }
-                       if (!strcmp("--refs", arg)) {
-                               flags |= REF_NORMAL;
-                               continue;
-                       }
-                       if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
-                               quiet = 1;
-                               continue;
-                       }
-                       if (!strcmp("--get-url", arg)) {
-                               get_url = 1;
-                               continue;
-                       }
-                       if (!strcmp("--exit-code", arg)) {
-                               /* return this code if no refs are reported */
-                               status = 2;
-                               continue;
-                       }
-                       usage(ls_remote_usage);
-               }
-               dest = arg;
-               i++;
-               break;
+       if (argc > 1) {
+               int i;
+               pattern = xcalloc(argc, sizeof(const char *));
+               for (i = 1; i < argc; i++)
+                       pattern[i - 1] = xstrfmt("*/%s", argv[i]);
        }
 
-       if (argv[i]) {
-               int j;
-               pattern = xcalloc(argc - i + 1, sizeof(const char *));
-               for (j = i; j < argc; j++)
-                       pattern[j - i] = xstrfmt("*/%s", argv[j]);
-       }
        remote = remote_get(dest);
        if (!remote) {
                if (dest)
@@ -125,7 +105,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)
                        continue;
                if (!tail_match(pattern, ref->name))
                        continue;
-               printf("%s      %s\n", oid_to_hex(&ref->old_oid), ref->name);
+               if (show_symref_target && ref->symref)
+                       printf("ref: %s\t%s\n", ref->symref, ref->name);
+               printf("%s\t%s\n", oid_to_hex(&ref->old_oid), ref->name);
                status = 0; /* we found something */
        }
        return status;
index 15bf95b3ac6c54727992103b1943515a1da32ff4..b98a3489bf24c0726b3847704e7ec0b658a79e51 100644 (file)
@@ -404,6 +404,7 @@ static void finish(struct commit *head_commit,
                         * We ignore errors in 'gc --auto', since the
                         * user should see them.
                         */
+                       close_all_packs();
                        run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
                }
        }
index a964d6be521c09a241ab0ccdc9f313e182769412..a237caacfdfc5905067bb6e3f9ae517b5f83ed17 100644 (file)
@@ -65,7 +65,7 @@ static const char *mktree_usage[] = {
        NULL
 };
 
-static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing)
+static void mktree_line(char *buf, size_t len, int nul_term_line, int allow_missing)
 {
        char *ptr, *ntr;
        unsigned mode;
@@ -97,7 +97,7 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m
        *ntr++ = 0; /* now at the beginning of SHA1 */
 
        path = ntr + 41;  /* at the beginning of name */
-       if (line_termination && path[0] == '"') {
+       if (!nul_term_line && path[0] == '"') {
                struct strbuf p_uq = STRBUF_INIT;
                if (unquote_c_style(&p_uq, path, NULL))
                        die("invalid quoting");
@@ -141,23 +141,25 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
 {
        struct strbuf sb = STRBUF_INIT;
        unsigned char sha1[20];
-       int line_termination = '\n';
+       int nul_term_line = 0;
        int allow_missing = 0;
        int is_batch_mode = 0;
        int got_eof = 0;
+       strbuf_getline_fn getline_fn;
 
        const struct option option[] = {
-               OPT_SET_INT('z', NULL, &line_termination, N_("input is NUL terminated"), '\0'),
+               OPT_BOOL('z', NULL, &nul_term_line, N_("input is NUL terminated")),
                OPT_SET_INT( 0 , "missing", &allow_missing, N_("allow missing objects"), 1),
                OPT_SET_INT( 0 , "batch", &is_batch_mode, N_("allow creation of more than one tree"), 1),
                OPT_END()
        };
 
        ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
+       getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
 
        while (!got_eof) {
                while (1) {
-                       if (strbuf_getline(&sb, stdin, line_termination) == EOF) {
+                       if (getline_fn(&sb, stdin) == EOF) {
                                got_eof = 1;
                                break;
                        }
@@ -167,7 +169,7 @@ int cmd_mktree(int ac, const char **av, const char *prefix)
                                        break;
                                die("input format error: (blank line only valid in batch mode)");
                        }
-                       mktree_line(sb.buf, sb.len, line_termination, allow_missing);
+                       mktree_line(sb.buf, sb.len, nul_term_line, allow_missing);
                }
                if (is_batch_mode && got_eof && used < 1) {
                        /*
index 52aa9af74be8d47780d4762185c5cbe09624b382..ed6f2222f4bf9c54535a7a23971c7749ca8d05d5 100644 (file)
@@ -286,11 +286,11 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
                if (!c)
                        return 0;
        } else {
-               init_notes(NULL, NULL, NULL, 0);
+               init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE);
                t = &default_notes_tree;
        }
 
-       while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+       while (strbuf_getline_lf(&buf, stdin) != EOF) {
                unsigned char from_obj[20], to_obj[20];
                struct strbuf **split;
                int err;
@@ -329,15 +329,18 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
        return ret;
 }
 
-static struct notes_tree *init_notes_check(const char *subcommand)
+static struct notes_tree *init_notes_check(const char *subcommand,
+                                          int flags)
 {
        struct notes_tree *t;
-       init_notes(NULL, NULL, NULL, 0);
+       const char *ref;
+       init_notes(NULL, NULL, NULL, flags);
        t = &default_notes_tree;
 
-       if (!starts_with(t->ref, "refs/notes/"))
+       ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref;
+       if (!starts_with(ref, "refs/notes/"))
                die("Refusing to %s notes in %s (outside of refs/notes/)",
-                   subcommand, t->ref);
+                   subcommand, ref);
        return t;
 }
 
@@ -360,7 +363,7 @@ static int list(int argc, const char **argv, const char *prefix)
                usage_with_options(git_notes_list_usage, options);
        }
 
-       t = init_notes_check("list");
+       t = init_notes_check("list", 0);
        if (argc) {
                if (get_sha1(argv[0], object))
                        die(_("Failed to resolve '%s' as a valid ref."), argv[0]);
@@ -420,7 +423,7 @@ static int add(int argc, const char **argv, const char *prefix)
        if (get_sha1(object_ref, object))
                die(_("Failed to resolve '%s' as a valid ref."), object_ref);
 
-       t = init_notes_check("add");
+       t = init_notes_check("add", NOTES_INIT_WRITABLE);
        note = get_note(t, object);
 
        if (note) {
@@ -511,7 +514,7 @@ static int copy(int argc, const char **argv, const char *prefix)
        if (get_sha1(object_ref, object))
                die(_("Failed to resolve '%s' as a valid ref."), object_ref);
 
-       t = init_notes_check("copy");
+       t = init_notes_check("copy", NOTES_INIT_WRITABLE);
        note = get_note(t, object);
 
        if (note) {
@@ -589,7 +592,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
        if (get_sha1(object_ref, object))
                die(_("Failed to resolve '%s' as a valid ref."), object_ref);
 
-       t = init_notes_check(argv[0]);
+       t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
        note = get_note(t, object);
 
        prepare_note_data(object, &d, edit ? note : NULL);
@@ -652,7 +655,7 @@ static int show(int argc, const char **argv, const char *prefix)
        if (get_sha1(object_ref, object))
                die(_("Failed to resolve '%s' as a valid ref."), object_ref);
 
-       t = init_notes_check("show");
+       t = init_notes_check("show", 0);
        note = get_note(t, object);
 
        if (!note)
@@ -806,10 +809,10 @@ static int merge(int argc, const char **argv, const char *prefix)
 
        o.local_ref = default_notes_ref();
        strbuf_addstr(&remote_ref, argv[0]);
-       expand_notes_ref(&remote_ref);
+       expand_loose_notes_ref(&remote_ref);
        o.remote_ref = remote_ref.buf;
 
-       t = init_notes_check("merge");
+       t = init_notes_check("merge", NOTES_INIT_WRITABLE);
 
        if (strategy) {
                if (parse_notes_merge_strategy(strategy, &o.strategy)) {
@@ -901,7 +904,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
        argc = parse_options(argc, argv, prefix, options,
                             git_notes_remove_usage, 0);
 
-       t = init_notes_check("remove");
+       t = init_notes_check("remove", NOTES_INIT_WRITABLE);
 
        if (!argc && !from_stdin) {
                retval = remove_one_note(t, "HEAD", flag);
@@ -943,7 +946,7 @@ static int prune(int argc, const char **argv, const char *prefix)
                usage_with_options(git_notes_prune_usage, options);
        }
 
-       t = init_notes_check("prune");
+       t = init_notes_check("prune", NOTES_INIT_WRITABLE);
 
        prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) |
                (show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) );
index 5145fc60a0377a7fb799555892909f979aca9076..10eff03967e0b9cb473d262b443949c55681fd1b 100644 (file)
@@ -22,7 +22,8 @@ enum rebase_type {
        REBASE_INVALID = -1,
        REBASE_FALSE = 0,
        REBASE_TRUE,
-       REBASE_PRESERVE
+       REBASE_PRESERVE,
+       REBASE_INTERACTIVE
 };
 
 /**
@@ -42,6 +43,8 @@ static enum rebase_type parse_config_rebase(const char *key, const char *value,
                return REBASE_TRUE;
        else if (!strcmp(value, "preserve"))
                return REBASE_PRESERVE;
+       else if (!strcmp(value, "interactive"))
+               return REBASE_INTERACTIVE;
 
        if (fatal)
                die(_("Invalid value for %s: %s"), key, value);
@@ -95,6 +98,7 @@ static int opt_force;
 static char *opt_tags;
 static char *opt_prune;
 static char *opt_recurse_submodules;
+static char *max_children;
 static int opt_dry_run;
 static char *opt_keep;
 static char *opt_depth;
@@ -112,7 +116,7 @@ static struct option pull_options[] = {
        /* Options passed to git-merge or git-rebase */
        OPT_GROUP(N_("Options related to merging")),
        { OPTION_CALLBACK, 'r', "rebase", &opt_rebase,
-         "false|true|preserve",
+         "false|true|preserve|interactive",
          N_("incorporate changes by rebasing rather than merging"),
          PARSE_OPT_OPTARG, parse_opt_rebase },
        OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
@@ -178,6 +182,9 @@ static struct option pull_options[] = {
                N_("on-demand"),
                N_("control recursive fetching of submodules"),
                PARSE_OPT_OPTARG),
+       OPT_PASSTHRU('j', "jobs", &max_children, N_("n"),
+               N_("number of submodules pulled in parallel"),
+               PARSE_OPT_OPTARG),
        OPT_BOOL(0, "dry-run", &opt_dry_run,
                N_("dry run")),
        OPT_PASSTHRU('k', "keep", &opt_keep, NULL,
@@ -378,7 +385,7 @@ static void get_merge_heads(struct sha1_array *merge_heads)
 
        if (!(fp = fopen(filename, "r")))
                die_errno(_("could not open '%s' for reading"), filename);
-       while (strbuf_getline(&sb, fp, '\n') != EOF) {
+       while (strbuf_getline_lf(&sb, fp) != EOF) {
                if (get_sha1_hex(sb.buf, sha1))
                        continue;  /* invalid line: does not start with SHA1 */
                if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t"))
@@ -525,6 +532,8 @@ static int run_fetch(const char *repo, const char **refspecs)
                argv_array_push(&args, opt_prune);
        if (opt_recurse_submodules)
                argv_array_push(&args, opt_recurse_submodules);
+       if (max_children)
+               argv_array_push(&args, max_children);
        if (opt_dry_run)
                argv_array_push(&args, "--dry-run");
        if (opt_keep)
@@ -772,6 +781,8 @@ static int run_rebase(const unsigned char *curr_head,
        /* Options passed to git-rebase */
        if (opt_rebase == REBASE_PRESERVE)
                argv_array_push(&args, "--preserve-merges");
+       else if (opt_rebase == REBASE_INTERACTIVE)
+               argv_array_push(&args, "--interactive");
        if (opt_diffstat)
                argv_array_push(&args, opt_diffstat);
        argv_array_pushv(&args, opt_strategies.argv);
index 8963dbdf3da816bba595f7c4fcfdfd8bcdcd8670..960ffc31e1537441a1120dceb120ce584b7edccf 100644 (file)
@@ -538,7 +538,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                OPT_BIT( 0 , "all", &flags, N_("push all refs"), TRANSPORT_PUSH_ALL),
                OPT_BIT( 0 , "mirror", &flags, N_("mirror all refs"),
                            (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-               OPT_BOOL( 0, "delete", &deleterefs, N_("delete refs")),
+               OPT_BOOL('d', "delete", &deleterefs, N_("delete refs")),
                OPT_BOOL( 0 , "tags", &tags, N_("push tags (can't be used with --all or --mirror)")),
                OPT_BIT('n' , "dry-run", &flags, N_("dry run"), TRANSPORT_PUSH_DRY_RUN),
                OPT_BIT( 0,  "porcelain", &flags, N_("machine-readable output"), TRANSPORT_PUSH_PORCELAIN),
index ca38131873aad1c5dd5b8001aceb39ed906b3c2d..f2d6761af66c8bcc43c2da13f69fa083cf1e1e60 100644 (file)
@@ -1618,7 +1618,7 @@ static void prepare_shallow_update(struct command *commands,
                                continue;
                        si->need_reachability_test[i]++;
                        for (k = 0; k < 32; k++)
-                               if (si->used_shallow[i][j] & (1 << k))
+                               if (si->used_shallow[i][j] & (1U << k))
                                        si->shallow_ref[j * 32 + k]++;
                }
 
@@ -1796,6 +1796,7 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
                                "gc", "--auto", "--quiet", NULL,
                        };
                        int opt = RUN_GIT_CMD | RUN_COMMAND_STDOUT_TO_STDERR;
+                       close_all_packs();
                        run_command_v_opt(argv_gc_auto, opt);
                }
                if (auto_update_server_info)
index 6694cf20efdc01fb59d0b6afa41f7b1557c9b2d5..2b2ff9b7d2152ce4ac9314bc8f111c02723703e6 100644 (file)
@@ -251,7 +251,7 @@ static int add(int argc, const char **argv)
 struct branch_info {
        char *remote_name;
        struct string_list merge;
-       int rebase;
+       enum { NO_REBASE, NORMAL_REBASE, INTERACTIVE_REBASE } rebase;
 };
 
 static struct string_list branch_list;
@@ -311,7 +311,9 @@ static int config_read_branches(const char *key, const char *value, void *cb)
                        if (v >= 0)
                                info->rebase = v;
                        else if (!strcmp(value, "preserve"))
-                               info->rebase = 1;
+                               info->rebase = NORMAL_REBASE;
+                       else if (!strcmp(value, "interactive"))
+                               info->rebase = INTERACTIVE_REBASE;
                }
        }
        return 0;
@@ -980,7 +982,9 @@ static int show_local_info_item(struct string_list_item *item, void *cb_data)
 
        printf("    %-*s ", show_info->width, item->string);
        if (branch_info->rebase) {
-               printf_ln(_("rebases onto remote %s"), merge->items[0].string);
+               printf_ln(_(branch_info->rebase == INTERACTIVE_REBASE ?
+                       "rebases interactively onto remote %s" :
+                       "rebases onto remote %s"), merge->items[0].string);
                return 0;
        } else if (show_info->any_rebase) {
                printf_ln(_(" merges with remote %s"), merge->items[0].string);
index 945611006a4ddcad1b834d87fe62698549ebb837..858db38f52e878a41cefdd47bbafd1250c7483b0 100644 (file)
@@ -266,7 +266,7 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
                return ret;
 
        out = xfdopen(cmd.out, "r");
-       while (strbuf_getline(&line, out, '\n') != EOF) {
+       while (strbuf_getline_lf(&line, out) != EOF) {
                if (line.len != 40)
                        die("repack: Expecting 40 character sha1 lines only from pack-objects.");
                string_list_append(&names, line.buf);
index 7e074aad408ee7d63d86643878ff5c5bb311f732..bd16876df5ff7bce4fbf348d84a0ebc4ea53e7d7 100644 (file)
@@ -383,7 +383,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
 
        /* get the usage up to the first line with a -- on it */
        for (;;) {
-               if (strbuf_getline(&sb, stdin, '\n') == EOF)
+               if (strbuf_getline(&sb, stdin) == EOF)
                        die("premature end of input");
                ALLOC_GROW(usage, unb + 1, usz);
                if (!strcmp("--", sb.buf)) {
@@ -396,7 +396,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
        }
 
        /* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
-       while (strbuf_getline(&sb, stdin, '\n') != EOF) {
+       while (strbuf_getline(&sb, stdin) != EOF) {
                const char *s;
                const char *help;
                struct option *o;
index 80b972f92fde3201bdf1cb8bd74c2b4ff53fa5ae..8829b09d0ba5d49edbad5f37f8246123dad3fd5f 100644 (file)
@@ -211,7 +211,7 @@ static int check_local_mod(unsigned char *head, int index_only)
                 * "intent to add" entry.
                 */
                if (local_changes && staged_changes) {
-                       if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
+                       if (!index_only || !ce_intent_to_add(ce))
                                string_list_append(&files_staged, name);
                }
                else if (!index_only) {
index f6e5d643c193d28b14107bf9a9e4ee7aa36ca933..5b9dd6a9d8ebe888c2fc912af3590b92737e7a99 100644 (file)
@@ -212,7 +212,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
                                argv_array_push(&all_refspecs, buf);
                } else {
                        struct strbuf line = STRBUF_INIT;
-                       while (strbuf_getline(&line, stdin, '\n') != EOF)
+                       while (strbuf_getline(&line, stdin) != EOF)
                                argv_array_push(&all_refspecs, line.buf);
                        strbuf_release(&line);
                }
index 35ebd17f80d7784f17023a4f76ac71e1317a94d0..bfc082e58467953c1e4c96fd27a884abea4f5127 100644 (file)
@@ -14,7 +14,26 @@ static char const * const shortlog_usage[] = {
        NULL
 };
 
-static int compare_by_number(const void *a1, const void *a2)
+/*
+ * The util field of our string_list_items will contain one of two things:
+ *
+ *   - if --summary is not in use, it will point to a string list of the
+ *     oneline subjects assigned to this author
+ *
+ *   - if --summary is in use, we don't need that list; we only need to know
+ *     its size. So we abuse the pointer slot to store our integer counter.
+ *
+ *  This macro accesses the latter.
+ */
+#define UTIL_TO_INT(x) ((intptr_t)(x)->util)
+
+static int compare_by_counter(const void *a1, const void *a2)
+{
+       const struct string_list_item *i1 = a1, *i2 = a2;
+       return UTIL_TO_INT(i2) - UTIL_TO_INT(i1);
+}
+
+static int compare_by_list(const void *a1, const void *a2)
 {
        const struct string_list_item *i1 = a1, *i2 = a2;
        const struct string_list *l1 = i1->util, *l2 = i2->util;
@@ -31,13 +50,9 @@ static void insert_one_record(struct shortlog *log,
                              const char *author,
                              const char *oneline)
 {
-       const char *dot3 = log->common_repo_prefix;
-       char *buffer, *p;
        struct string_list_item *item;
        const char *mailbuf, *namebuf;
        size_t namelen, maillen;
-       const char *eol;
-       struct strbuf subject = STRBUF_INIT;
        struct strbuf namemailbuf = STRBUF_INIT;
        struct ident_split ident;
 
@@ -56,98 +71,95 @@ static void insert_one_record(struct shortlog *log,
                strbuf_addf(&namemailbuf, " <%.*s>", (int)maillen, mailbuf);
 
        item = string_list_insert(&log->list, namemailbuf.buf);
-       if (item->util == NULL)
-               item->util = xcalloc(1, sizeof(struct string_list));
-
-       /* Skip any leading whitespace, including any blank lines. */
-       while (*oneline && isspace(*oneline))
-               oneline++;
-       eol = strchr(oneline, '\n');
-       if (!eol)
-               eol = oneline + strlen(oneline);
-       if (starts_with(oneline, "[PATCH")) {
-               char *eob = strchr(oneline, ']');
-               if (eob && (!eol || eob < eol))
-                       oneline = eob + 1;
-       }
-       while (*oneline && isspace(*oneline) && *oneline != '\n')
-               oneline++;
-       format_subject(&subject, oneline, " ");
-       buffer = strbuf_detach(&subject, NULL);
-
-       if (dot3) {
-               int dot3len = strlen(dot3);
-               if (dot3len > 5) {
-                       while ((p = strstr(buffer, dot3)) != NULL) {
-                               int taillen = strlen(p) - dot3len;
-                               memcpy(p, "/.../", 5);
-                               memmove(p + 5, p + dot3len, taillen + 1);
+
+       if (log->summary)
+               item->util = (void *)(UTIL_TO_INT(item) + 1);
+       else {
+               const char *dot3 = log->common_repo_prefix;
+               char *buffer, *p;
+               struct strbuf subject = STRBUF_INIT;
+               const char *eol;
+
+               /* Skip any leading whitespace, including any blank lines. */
+               while (*oneline && isspace(*oneline))
+                       oneline++;
+               eol = strchr(oneline, '\n');
+               if (!eol)
+                       eol = oneline + strlen(oneline);
+               if (starts_with(oneline, "[PATCH")) {
+                       char *eob = strchr(oneline, ']');
+                       if (eob && (!eol || eob < eol))
+                               oneline = eob + 1;
+               }
+               while (*oneline && isspace(*oneline) && *oneline != '\n')
+                       oneline++;
+               format_subject(&subject, oneline, " ");
+               buffer = strbuf_detach(&subject, NULL);
+
+               if (dot3) {
+                       int dot3len = strlen(dot3);
+                       if (dot3len > 5) {
+                               while ((p = strstr(buffer, dot3)) != NULL) {
+                                       int taillen = strlen(p) - dot3len;
+                                       memcpy(p, "/.../", 5);
+                                       memmove(p + 5, p + dot3len, taillen + 1);
+                               }
                        }
                }
-       }
 
-       string_list_append(item->util, buffer);
+               if (item->util == NULL)
+                       item->util = xcalloc(1, sizeof(struct string_list));
+               string_list_append(item->util, buffer);
+       }
 }
 
 static void read_from_stdin(struct shortlog *log)
 {
-       char author[1024], oneline[1024];
+       struct strbuf author = STRBUF_INIT;
+       struct strbuf oneline = STRBUF_INIT;
 
-       while (fgets(author, sizeof(author), stdin) != NULL) {
-               if (!(author[0] == 'A' || author[0] == 'a') ||
-                   !starts_with(author + 1, "uthor: "))
+       while (strbuf_getline_lf(&author, stdin) != EOF) {
+               const char *v;
+               if (!skip_prefix(author.buf, "Author: ", &v) &&
+                   !skip_prefix(author.buf, "author ", &v))
                        continue;
-               while (fgets(oneline, sizeof(oneline), stdin) &&
-                      oneline[0] != '\n')
+               while (strbuf_getline_lf(&oneline, stdin) != EOF &&
+                      oneline.len)
                        ; /* discard headers */
-               while (fgets(oneline, sizeof(oneline), stdin) &&
-                      oneline[0] == '\n')
+               while (strbuf_getline_lf(&oneline, stdin) != EOF &&
+                      !oneline.len)
                        ; /* discard blanks */
-               insert_one_record(log, author + 8, oneline);
+               insert_one_record(log, v, oneline.buf);
        }
+       strbuf_release(&author);
+       strbuf_release(&oneline);
 }
 
 void shortlog_add_commit(struct shortlog *log, struct commit *commit)
 {
-       const char *author = NULL, *buffer;
-       struct strbuf buf = STRBUF_INIT;
-       struct strbuf ufbuf = STRBUF_INIT;
-
-       pp_commit_easy(CMIT_FMT_RAW, commit, &buf);
-       buffer = buf.buf;
-       while (*buffer && *buffer != '\n') {
-               const char *eol = strchr(buffer, '\n');
-
-               if (eol == NULL)
-                       eol = buffer + strlen(buffer);
+       struct strbuf author = STRBUF_INIT;
+       struct strbuf oneline = STRBUF_INIT;
+       struct pretty_print_context ctx = {0};
+
+       ctx.fmt = CMIT_FMT_USERFORMAT;
+       ctx.abbrev = log->abbrev;
+       ctx.subject = "";
+       ctx.after_subject = "";
+       ctx.date_mode.type = DATE_NORMAL;
+       ctx.output_encoding = get_log_output_encoding();
+
+       format_commit_message(commit, "%an <%ae>", &author, &ctx);
+       if (!log->summary) {
+               if (log->user_format)
+                       pretty_print_commit(&ctx, commit, &oneline);
                else
-                       eol++;
-
-               if (starts_with(buffer, "author "))
-                       author = buffer + 7;
-               buffer = eol;
-       }
-       if (!author) {
-               warning(_("Missing author: %s"),
-                   oid_to_hex(&commit->object.oid));
-               return;
+                       format_commit_message(commit, "%s", &oneline, &ctx);
        }
-       if (log->user_format) {
-               struct pretty_print_context ctx = {0};
-               ctx.fmt = CMIT_FMT_USERFORMAT;
-               ctx.abbrev = log->abbrev;
-               ctx.subject = "";
-               ctx.after_subject = "";
-               ctx.date_mode.type = DATE_NORMAL;
-               ctx.output_encoding = get_log_output_encoding();
-               pretty_print_commit(&ctx, commit, &ufbuf);
-               buffer = ufbuf.buf;
-       } else if (*buffer) {
-               buffer++;
-       }
-       insert_one_record(log, author, !*buffer ? "<none>" : buffer);
-       strbuf_release(&ufbuf);
-       strbuf_release(&buf);
+
+       insert_one_record(log, author.buf, oneline.len ? oneline.buf : "<none>");
+
+       strbuf_release(&author);
+       strbuf_release(&oneline);
 }
 
 static void get_from_rev(struct rev_info *rev, struct shortlog *log)
@@ -294,14 +306,14 @@ void shortlog_output(struct shortlog *log)
 
        if (log->sort_by_number)
                qsort(log->list.items, log->list.nr, sizeof(struct string_list_item),
-                       compare_by_number);
+                     log->summary ? compare_by_counter : compare_by_list);
        for (i = 0; i < log->list.nr; i++) {
-               struct string_list *onelines = log->list.items[i].util;
-
+               const struct string_list_item *item = &log->list.items[i];
                if (log->summary) {
-                       printf("%6d\t%s\n", onelines->nr, log->list.items[i].string);
+                       printf("%6d\t%s\n", (int)UTIL_TO_INT(item), item->string);
                } else {
-                       printf("%s (%d):\n", log->list.items[i].string, onelines->nr);
+                       struct string_list *onelines = item->util;
+                       printf("%s (%d):\n", item->string, onelines->nr);
                        for (j = onelines->nr - 1; j >= 0; j--) {
                                const char *msg = onelines->items[j].string;
 
@@ -314,11 +326,11 @@ void shortlog_output(struct shortlog *log)
                                        printf("      %s\n", msg);
                        }
                        putchar('\n');
+                       onelines->strdup_strings = 1;
+                       string_list_clear(onelines, 0);
+                       free(onelines);
                }
 
-               onelines->strdup_strings = 1;
-               string_list_clear(onelines, 0);
-               free(onelines);
                log->list.items[i].util = NULL;
        }
 
index 8db8c87e57ef05edadce8de19316572498c40753..1705c9466546c7de52b12d3fbafbbe7b6d43cf4e 100644 (file)
@@ -44,11 +44,11 @@ static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, con
        if (!format) {
                if (filter->lines) {
                        to_free = xstrfmt("%s %%(contents:lines=%d)",
-                                         "%(align:15)%(refname:short)%(end)",
+                                         "%(align:15)%(refname:strip=2)%(end)",
                                          filter->lines);
                        format = to_free;
                } else
-                       format = "%(refname:short)";
+                       format = "%(refname:strip=2)";
        }
 
        verify_ref_format(format);
index 7431938fa654ba9af524a7018ab2c7be8242caaa..dbc23a46b13bee7ff532232c0e1d821c565fd2fb 100644 (file)
@@ -35,6 +35,15 @@ static int mark_skip_worktree_only;
 #define UNMARK_FLAG 2
 static struct strbuf mtime_dir = STRBUF_INIT;
 
+/* Untracked cache mode */
+enum uc_mode {
+       UC_UNSPECIFIED = -1,
+       UC_DISABLE = 0,
+       UC_ENABLE,
+       UC_TEST,
+       UC_FORCE
+};
+
 __attribute__((format (printf, 1, 2)))
 static void report(const char *fmt, ...)
 {
@@ -121,7 +130,7 @@ static int test_if_untracked_cache_is_supported(void)
        if (!mkdtemp(mtime_dir.buf))
                die_errno("Could not make temporary directory");
 
-       fprintf(stderr, _("Testing "));
+       fprintf(stderr, _("Testing mtime in '%s' "), xgetcwd());
        atexit(remove_test_directory);
        xstat_mtime_dir(&st);
        fill_stat_data(&base, &st);
@@ -468,12 +477,14 @@ static void update_one(const char *path)
        report("add '%s'", path);
 }
 
-static void read_index_info(int line_termination)
+static void read_index_info(int nul_term_line)
 {
        struct strbuf buf = STRBUF_INIT;
        struct strbuf uq = STRBUF_INIT;
+       strbuf_getline_fn getline_fn;
 
-       while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
+       getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
+       while (getline_fn(&buf, stdin) != EOF) {
                char *ptr, *tab;
                char *path_name;
                unsigned char sha1[20];
@@ -522,7 +533,7 @@ static void read_index_info(int line_termination)
                        goto bad_line;
 
                path_name = ptr;
-               if (line_termination && path_name[0] == '"') {
+               if (!nul_term_line && path_name[0] == '"') {
                        strbuf_reset(&uq);
                        if (unquote_c_style(&uq, path_name, NULL)) {
                                die("git update-index: bad quoting of path name");
@@ -844,12 +855,12 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
 static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx,
                              const struct option *opt, int unset)
 {
-       int *line_termination = opt->value;
+       int *nul_term_line = opt->value;
 
        if (ctx->argc != 1)
                return error("option '%s' must be the last argument", opt->long_name);
        allow_add = allow_replace = allow_remove = 1;
-       read_index_info(*line_termination);
+       read_index_info(*nul_term_line);
        return 0;
 }
 
@@ -901,8 +912,8 @@ static int reupdate_callback(struct parse_opt_ctx_t *ctx,
 
 int cmd_update_index(int argc, const char **argv, const char *prefix)
 {
-       int newfd, entries, has_errors = 0, line_termination = '\n';
-       int untracked_cache = -1;
+       int newfd, entries, has_errors = 0, nul_term_line = 0;
+       enum uc_mode untracked_cache = UC_UNSPECIFIED;
        int read_from_stdin = 0;
        int prefix_length = prefix ? strlen(prefix) : 0;
        int preferred_index_format = 0;
@@ -912,6 +923,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        int split_index = -1;
        struct lock_file *lock_file;
        struct parse_opt_ctx_t ctx;
+       strbuf_getline_fn getline_fn;
        int parseopt_state = PARSE_OPT_UNKNOWN;
        struct option options[] = {
                OPT_BIT('q', NULL, &refresh_args.flags,
@@ -963,13 +975,13 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                        N_("add to index only; do not add content to object database"), 1),
                OPT_SET_INT(0, "force-remove", &force_remove,
                        N_("remove named paths even if present in worktree"), 1),
-               OPT_SET_INT('z', NULL, &line_termination,
-                       N_("with --stdin: input lines are terminated by null bytes"), '\0'),
+               OPT_BOOL('z', NULL, &nul_term_line,
+                        N_("with --stdin: input lines are terminated by null bytes")),
                {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL,
                        N_("read list of paths to be updated from standard input"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
                        (parse_opt_cb *) stdin_callback},
-               {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &line_termination, NULL,
+               {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL,
                        N_("add entries from standard input to the index"),
                        PARSE_OPT_NONEG | PARSE_OPT_NOARG,
                        (parse_opt_cb *) stdin_cacheinfo_callback},
@@ -996,8 +1008,10 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                        N_("enable or disable split index")),
                OPT_BOOL(0, "untracked-cache", &untracked_cache,
                        N_("enable/disable untracked cache")),
+               OPT_SET_INT(0, "test-untracked-cache", &untracked_cache,
+                           N_("test if the filesystem supports untracked cache"), UC_TEST),
                OPT_SET_INT(0, "force-untracked-cache", &untracked_cache,
-                           N_("enable untracked cache without testing the filesystem"), 2),
+                           N_("enable untracked cache without testing the filesystem"), UC_FORCE),
                OPT_END()
        };
 
@@ -1057,6 +1071,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                }
        }
        argc = parse_options_end(&ctx);
+
+       getline_fn = nul_term_line ? strbuf_getline_nul : strbuf_getline_lf;
        if (preferred_index_format) {
                if (preferred_index_format < INDEX_FORMAT_LB ||
                    INDEX_FORMAT_UB < preferred_index_format)
@@ -1073,9 +1089,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT;
 
                setup_work_tree();
-               while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
+               while (getline_fn(&buf, stdin) != EOF) {
                        char *p;
-                       if (line_termination && buf.buf[0] == '"') {
+                       if (!nul_term_line && buf.buf[0] == '"') {
                                strbuf_reset(&nbuf);
                                if (unquote_c_style(&nbuf, buf.buf, NULL))
                                        die("line is badly quoted");
@@ -1104,27 +1120,32 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                the_index.split_index = NULL;
                the_index.cache_changed |= SOMETHING_CHANGED;
        }
-       if (untracked_cache > 0) {
-               struct untracked_cache *uc;
 
-               if (untracked_cache < 2) {
-                       setup_work_tree();
-                       if (!test_if_untracked_cache_is_supported())
-                               return 1;
-               }
-               if (!the_index.untracked) {
-                       uc = xcalloc(1, sizeof(*uc));
-                       strbuf_init(&uc->ident, 100);
-                       uc->exclude_per_dir = ".gitignore";
-                       /* should be the same flags used by git-status */
-                       uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
-                       the_index.untracked = uc;
-               }
-               add_untracked_ident(the_index.untracked);
-               the_index.cache_changed |= UNTRACKED_CHANGED;
-       } else if (!untracked_cache && the_index.untracked) {
-               the_index.untracked = NULL;
-               the_index.cache_changed |= UNTRACKED_CHANGED;
+       switch (untracked_cache) {
+       case UC_UNSPECIFIED:
+               break;
+       case UC_DISABLE:
+               if (git_config_get_untracked_cache() == 1)
+                       warning("core.untrackedCache is set to true; "
+                               "remove or change it, if you really want to "
+                               "disable the untracked cache");
+               remove_untracked_cache(&the_index);
+               report(_("Untracked cache disabled"));
+               break;
+       case UC_TEST:
+               setup_work_tree();
+               return !test_if_untracked_cache_is_supported();
+       case UC_ENABLE:
+       case UC_FORCE:
+               if (git_config_get_untracked_cache() == 0)
+                       warning("core.untrackedCache is set to false; "
+                               "remove or change it, if you really want to "
+                               "enable the untracked cache");
+               add_untracked_cache(&the_index);
+               report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
+               break;
+       default:
+               die("Bug: bad untracked_cache value: %d", untracked_cache);
        }
 
        if (active_cache_changed) {
index a59e6f1e1fcfb65bd2fe9cdba0db60d6d87e7d96..20ee7b52df0c33d4473a198270705dffead01cdc 100644 (file)
@@ -377,7 +377,7 @@ static int update_one(struct cache_tree *it,
                 * they are not part of generated trees. Invalidate up
                 * to root to force cache-tree users to read elsewhere.
                 */
-               if (ce->ce_flags & CE_INTENT_TO_ADD) {
+               if (ce_intent_to_add(ce)) {
                        to_invalidate = 1;
                        continue;
                }
diff --git a/cache.h b/cache.h
index c63fcc113a6e511a53f0170a07bd5dbbf12cc120..26640b421d938a215236935d35c2d6b4f37fee6d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -9,6 +9,7 @@
 #include "convert.h"
 #include "trace.h"
 #include "string-list.h"
+#include "pack-revindex.h"
 
 #include SHA1_HEADER
 #ifndef platform_SHA_CTX
@@ -214,7 +215,7 @@ struct cache_entry {
 #define CE_INTENT_TO_ADD     (1 << 29)
 #define CE_SKIP_WORKTREE     (1 << 30)
 /* CE_EXTENDED2 is for future extension */
-#define CE_EXTENDED2         (1 << 31)
+#define CE_EXTENDED2         (1U << 31)
 
 #define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD | CE_SKIP_WORKTREE)
 
@@ -259,6 +260,7 @@ static inline unsigned create_ce_flags(unsigned stage)
 #define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
 #define ce_skip_worktree(ce) ((ce)->ce_flags & CE_SKIP_WORKTREE)
 #define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
+#define ce_intent_to_add(ce) ((ce)->ce_flags & CE_INTENT_TO_ADD)
 
 #define ce_permissions(mode) (((mode) & 0100) ? 0755 : 0644)
 static inline unsigned int create_ce_mode(unsigned int mode)
@@ -456,7 +458,6 @@ extern char *git_work_tree_cfg;
 extern int is_inside_work_tree(void);
 extern const char *get_git_dir(void);
 extern const char *get_git_common_dir(void);
-extern int is_git_directory(const char *path);
 extern char *get_object_directory(void);
 extern char *get_index_file(void);
 extern char *get_graft_file(void);
@@ -467,6 +468,25 @@ extern const char *get_git_namespace(void);
 extern const char *strip_namespace(const char *namespaced_ref);
 extern const char *get_git_work_tree(void);
 
+/*
+ * Return true if the given path is a git directory; note that this _just_
+ * looks at the directory itself. If you want to know whether "foo/.git"
+ * is a repository, you must feed that path, not just "foo".
+ */
+extern int is_git_directory(const char *path);
+
+/*
+ * Return 1 if the given path is the root of a git repository or
+ * submodule, else 0. Will not return 1 for bare repositories with the
+ * exception of creating a bare repository in "foo/.git" and calling
+ * is_git_repository("foo").
+ *
+ * If we run into read errors, we err on the side of saying "yes, it is",
+ * as we usually consider sub-repos precious, and would prefer to err on the
+ * side of not disrupting or deleting them.
+ */
+extern int is_nonbare_repository_dir(struct strbuf *path);
+
 #define READ_GITFILE_ERR_STAT_FAILED 1
 #define READ_GITFILE_ERR_NOT_A_FILE 2
 #define READ_GITFILE_ERR_OPEN_FAILED 3
@@ -1299,6 +1319,7 @@ extern struct packed_git {
                 freshened:1,
                 do_not_close:1;
        unsigned char sha1[20];
+       struct revindex_entry *revindex;
        /* something like ".git/objects/pack/xxxxx.pack" */
        char pack_name[FLEX_ARRAY]; /* more */
 } *packed_git;
@@ -1603,6 +1624,14 @@ extern int git_config_get_bool(const char *key, int *dest);
 extern int git_config_get_bool_or_int(const char *key, int *is_bool, int *dest);
 extern int git_config_get_maybe_bool(const char *key, int *dest);
 extern int git_config_get_pathname(const char *key, const char **dest);
+extern int git_config_get_untracked_cache(void);
+
+/*
+ * This is a hack for test programs like test-dump-untracked-cache to
+ * ensure that they do not modify the untracked cache when reading it.
+ * Do not use it otherwise!
+ */
+extern int ignore_untracked_cache_config;
 
 struct key_value_info {
        const char *filename;
index d8f8a3c6dc039ff8891d04857be737b29259d7c6..96bd9533b448e56176a335a41e32f9bb2dd24d03 100644 (file)
@@ -1,15 +1,71 @@
 #include "../git-compat-util.h"
+#include "../strbuf.h"
 
 /* Adapted from libiberty's basename.c.  */
 char *gitbasename (char *path)
 {
        const char *base;
-       /* Skip over the disk name in MSDOS pathnames. */
-       if (has_dos_drive_prefix(path))
-               path += 2;
+
+       if (path)
+               skip_dos_drive_prefix(&path);
+
+       if (!path || !*path)
+               return ".";
+
        for (base = path; *path; path++) {
-               if (is_dir_sep(*path))
-                       base = path + 1;
+               if (!is_dir_sep(*path))
+                       continue;
+               do {
+                       path++;
+               } while (is_dir_sep(*path));
+               if (*path)
+                       base = path;
+               else
+                       while (--path != base && is_dir_sep(*path))
+                               *path = '\0';
        }
        return (char *)base;
 }
+
+char *gitdirname(char *path)
+{
+       static struct strbuf buf = STRBUF_INIT;
+       char *p = path, *slash = NULL, c;
+       int dos_drive_prefix;
+
+       if (!p)
+               return ".";
+
+       if ((dos_drive_prefix = skip_dos_drive_prefix(&p)) && !*p)
+               goto dot;
+
+       /*
+        * POSIX.1-2001 says dirname("/") should return "/", and dirname("//")
+        * should return "//", but dirname("///") should return "/" again.
+        */
+       if (is_dir_sep(*p)) {
+               if (!p[1] || (is_dir_sep(p[1]) && !p[2]))
+                       return path;
+               slash = ++p;
+       }
+       while ((c = *(p++)))
+               if (is_dir_sep(c)) {
+                       char *tentative = p - 1;
+
+                       /* POSIX.1-2001 says to ignore trailing slashes */
+                       while (is_dir_sep(*p))
+                               p++;
+                       if (*p)
+                               slash = tentative;
+               }
+
+       if (slash) {
+               *slash = '\0';
+               return path;
+       }
+
+dot:
+       strbuf_reset(&buf);
+       strbuf_addf(&buf, "%.*s.", dos_drive_prefix, path);
+       return buf.buf;
+}
index 7fed637ed09648b155441e883302e6b96afb7202..d47c0035449b412ee074c9a94c0f5281211f5f7e 100644 (file)
@@ -149,11 +149,12 @@ static inline uint64_t git_bswap64(uint64_t x)
  * and is faster on architectures with memory alignment issues.
  */
 
-#if defined(__i386__) || defined(__x86_64__) || \
+#if !defined(NO_UNALIGNED_LOADS) && ( \
+    defined(__i386__) || defined(__x86_64__) || \
     defined(_M_IX86) || defined(_M_X64) || \
     defined(__ppc__) || defined(__ppc64__) || \
     defined(__powerpc__) || defined(__powerpc64__) || \
-    defined(__s390__) || defined(__s390x__)
+    defined(__s390__) || defined(__s390x__))
 
 #define get_be16(p)    ntohs(*(unsigned short *)(p))
 #define get_be32(p)    ntohl(*(unsigned int *)(p))
index 5edea29508d06fdc2daea540edadffdebd54173e..77a51d3f72ebf8a3fa53b72e93b26f4e60c710b8 100644 (file)
@@ -6,6 +6,8 @@
 #include "../run-command.h"
 #include "../cache.h"
 
+#define HCAST(type, handle) ((type)(intptr_t)handle)
+
 static const int delay[] = { 0, 1, 10, 20, 40 };
 
 int err_win_to_posix(DWORD winerr)
@@ -691,13 +693,13 @@ int pipe(int filedes[2])
                errno = err_win_to_posix(GetLastError());
                return -1;
        }
-       filedes[0] = _open_osfhandle((int)h[0], O_NOINHERIT);
+       filedes[0] = _open_osfhandle(HCAST(int, h[0]), O_NOINHERIT);
        if (filedes[0] < 0) {
                CloseHandle(h[0]);
                CloseHandle(h[1]);
                return -1;
        }
-       filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT);
+       filedes[1] = _open_osfhandle(HCAST(int, h[1]), O_NOINHERIT);
        if (filedes[1] < 0) {
                close(filedes[0]);
                CloseHandle(h[1]);
@@ -1846,7 +1848,8 @@ void mingw_open_html(const char *unixpath)
                die("cannot run browser");
 
        printf("Launching default browser to display HTML ...\n");
-       r = (int)ShellExecute(NULL, "open", htmlpath, NULL, "\\", SW_SHOWNORMAL);
+       r = HCAST(int, ShellExecute(NULL, "open", htmlpath,
+                               NULL, "\\", SW_SHOWNORMAL));
        FreeLibrary(shell32);
        /* see the MSDN documentation referring to the result codes here */
        if (r <= 32) {
@@ -1932,28 +1935,31 @@ pid_t waitpid(pid_t pid, int *status, int options)
        return -1;
 }
 
+int mingw_skip_dos_drive_prefix(char **path)
+{
+       int ret = has_dos_drive_prefix(*path);
+       *path += ret;
+       return ret;
+}
+
 int mingw_offset_1st_component(const char *path)
 {
-       int offset = 0;
-       if (has_dos_drive_prefix(path))
-               offset = 2;
+       char *pos = (char *)path;
 
        /* unc paths */
-       else if (is_dir_sep(path[0]) && is_dir_sep(path[1])) {
-
+       if (!skip_dos_drive_prefix(&pos) &&
+                       is_dir_sep(pos[0]) && is_dir_sep(pos[1])) {
                /* skip server name */
-               char *pos = strpbrk(path + 2, "\\/");
+               pos = strpbrk(pos + 2, "\\/");
                if (!pos)
                        return 0; /* Error: malformed unc path */
 
                do {
                        pos++;
                } while (*pos && !is_dir_sep(*pos));
-
-               offset = pos - path;
        }
 
-       return offset + is_dir_sep(path[offset]);
+       return pos + is_dir_sep(*pos) - path;
 }
 
 int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen)
index 57ca477d1f100a7ddb1cc9cb693d050e32ae0eb0..8c5bf5076bfe25ce5b12235c035cff95a4900f2c 100644 (file)
@@ -1,27 +1,43 @@
+#ifdef __MINGW64_VERSION_MAJOR
+#include <stdint.h>
+#include <wchar.h>
+typedef _sigset_t sigset_t;
+#endif
 #include <winsock2.h>
 #include <ws2tcpip.h>
 
+/* MinGW-w64 reports to have flockfile, but it does not actually have it. */
+#ifdef __MINGW64_VERSION_MAJOR
+#undef _POSIX_THREAD_SAFE_FUNCTIONS
+#endif
+
 /*
  * things that are not available in header files
  */
 
-typedef int pid_t;
 typedef int uid_t;
 typedef int socklen_t;
+#ifndef __MINGW64_VERSION_MAJOR
+typedef int pid_t;
 #define hstrerror strerror
+#endif
 
 #define S_IFLNK    0120000 /* Symbolic link */
 #define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
 #define S_ISSOCK(x) 0
 
+#ifndef S_IRWXG
 #define S_IRGRP 0
 #define S_IWGRP 0
 #define S_IXGRP 0
 #define S_IRWXG (S_IRGRP | S_IWGRP | S_IXGRP)
+#endif
+#ifndef S_IRWXO
 #define S_IROTH 0
 #define S_IWOTH 0
 #define S_IXOTH 0
 #define S_IRWXO (S_IROTH | S_IWOTH | S_IXOTH)
+#endif
 
 #define S_ISUID 0004000
 #define S_ISGID 0002000
@@ -100,8 +116,10 @@ static inline int symlink(const char *oldpath, const char *newpath)
 { errno = ENOSYS; return -1; }
 static inline int fchmod(int fildes, mode_t mode)
 { errno = ENOSYS; return -1; }
+#ifndef __MINGW64_VERSION_MAJOR
 static inline pid_t fork(void)
 { errno = ENOSYS; return -1; }
+#endif
 static inline unsigned int alarm(unsigned int seconds)
 { return 0; }
 static inline int fsync(int fd)
@@ -176,8 +194,10 @@ int pipe(int filedes[2]);
 unsigned int sleep (unsigned int seconds);
 int mkstemp(char *template);
 int gettimeofday(struct timeval *tv, void *tz);
+#ifndef __MINGW64_VERSION_MAJOR
 struct tm *gmtime_r(const time_t *timep, struct tm *result);
 struct tm *localtime_r(const time_t *timep, struct tm *result);
+#endif
 int getpagesize(void); /* defined in MinGW's libgcc.a */
 struct passwd *getpwuid(uid_t uid);
 int setitimer(int type, struct itimerval *in, struct itimerval *out);
@@ -301,8 +321,10 @@ static inline int getrlimit(int resource, struct rlimit *rlp)
 /*
  * Use mingw specific stat()/lstat()/fstat() implementations on Windows.
  */
+#ifndef __MINGW64_VERSION_MAJOR
 #define off_t off64_t
 #define lseek _lseeki64
+#endif
 
 /* use struct stat with 64 bit st_size */
 #ifdef stat
@@ -361,7 +383,10 @@ HANDLE winansi_get_osfhandle(int fd);
  * git specific compatibility
  */
 
-#define has_dos_drive_prefix(path) (isalpha(*(path)) && (path)[1] == ':')
+#define has_dos_drive_prefix(path) \
+       (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0)
+int mingw_skip_dos_drive_prefix(char **path);
+#define skip_dos_drive_prefix mingw_skip_dos_drive_prefix
 #define is_dir_sep(c) ((c) == '/' || (c) == '\\')
 static inline char *mingw_find_last_dir_sep(const char *path)
 {
@@ -375,8 +400,12 @@ static inline char *mingw_find_last_dir_sep(const char *path)
 int mingw_offset_1st_component(const char *path);
 #define offset_1st_component mingw_offset_1st_component
 #define PATH_SEP ';'
+#ifndef __MINGW64_VERSION_MAJOR
 #define PRIuMAX "I64u"
 #define PRId64 "I64d"
+#else
+#include <inttypes.h>
+#endif
 
 void mingw_open_html(const char *path);
 #define open_html mingw_open_html
index f216a2a7d3d57b5ca7e791494b01f9604ba51e3e..b833ff9225e73ae830cab6057b6137864a6937c8 100644 (file)
@@ -720,6 +720,9 @@ struct mallinfo {
   inlining are defined as macros, so these aren't used for them.
 */
 
+#ifdef __MINGW64_VERSION_MAJOR
+#undef FORCEINLINE
+#endif
 #ifndef FORCEINLINE
   #if defined(__GNUC__)
 #define FORCEINLINE __inline __attribute__ ((always_inline))
@@ -1382,6 +1385,7 @@ LONG __cdecl _InterlockedExchange(LONG volatile *Target, LONG Value);
 
   /*** Atomic operations ***/
   #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
+    #undef _ReadWriteBarrier
     #define _ReadWriteBarrier() __sync_synchronize()
   #else
     static __inline__ __attribute__((always_inline)) long __sync_lock_test_and_set(volatile long * const Target, const long Value)
@@ -1798,9 +1802,10 @@ struct win32_mlock_t
   volatile long threadid;
 };
 
+static inline int return_0(int i) { return 0; }
 #define MLOCK_T               struct win32_mlock_t
 #define CURRENT_THREAD        win32_getcurrentthreadid()
-#define INITIAL_LOCK(sl)      (memset(sl, 0, sizeof(MLOCK_T)), 0)
+#define INITIAL_LOCK(sl)      (memset(sl, 0, sizeof(MLOCK_T)), return_0(0))
 #define ACQUIRE_LOCK(sl)      win32_acquire_lock(sl)
 #define RELEASE_LOCK(sl)      win32_release_lock(sl)
 #define TRY_LOCK(sl)          win32_try_lock(sl)
index db4e03ed793eead425f2fa53c2a1777b1401269a..b10adc780fc334383f2684d21fa1c5a8d92771b9 100644 (file)
@@ -76,7 +76,7 @@
 
 #ifdef WIN32_NATIVE
 
-#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
+#define IsConsoleHandle(h) (((long) (intptr_t) (h) & 3) == 3)
 
 static BOOL
 IsSocketHandle (HANDLE h)
index 313897d581f0c5f2eae4d09b82d6ff8b98a21ea4..fa13ee672db33ef2fbcc16295230b99aa9d4f595 100644 (file)
@@ -122,7 +122,7 @@ char *git_terminal_prompt(const char *prompt, int echo)
        fputs(prompt, output_fh);
        fflush(output_fh);
 
-       r = strbuf_getline(&buf, input_fh, '\n');
+       r = strbuf_getline_lf(&buf, input_fh);
        if (!echo) {
                putc('\n', output_fh);
                fflush(output_fh);
index 8ad187344fd93e894a2f1cbfaa0fb59fd832de5b..20b35a283ca71070086728384fffadf98aa17bba 100644 (file)
  */
 #define pthread_mutex_t CRITICAL_SECTION
 
-#define pthread_mutex_init(a,b) (InitializeCriticalSection((a)), 0)
+static inline int return_0(int i) {
+       return 0;
+}
+#define pthread_mutex_init(a,b) return_0((InitializeCriticalSection((a)), 0))
 #define pthread_mutex_destroy(a) DeleteCriticalSection((a))
 #define pthread_mutex_lock EnterCriticalSection
 #define pthread_mutex_unlock LeaveCriticalSection
@@ -77,7 +80,7 @@ extern pthread_t pthread_self(void);
 
 static inline int pthread_exit(void *ret)
 {
-       ExitThread((DWORD)ret);
+       ExitThread((DWORD)(intptr_t)ret);
 }
 
 typedef DWORD pthread_key_t;
index ceff55bd67696403f374f68ae6d3db97f603aebe..5dfa5ed61f49c4032d82c5825c0c43c86e04799f 100644 (file)
@@ -23,6 +23,7 @@ static HANDLE hthread, hread, hwrite;
 static HANDLE hconsole1, hconsole2;
 
 #ifdef __MINGW32__
+#if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 5
 typedef struct _CONSOLE_FONT_INFOEX {
        ULONG cbSize;
        DWORD nFont;
@@ -32,6 +33,7 @@ typedef struct _CONSOLE_FONT_INFOEX {
        WCHAR FaceName[LF_FACESIZE];
 } CONSOLE_FONT_INFOEX, *PCONSOLE_FONT_INFOEX;
 #endif
+#endif
 
 typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL,
                PCONSOLE_FONT_INFOEX);
@@ -452,7 +454,8 @@ static HANDLE duplicate_handle(HANDLE hnd)
        HANDLE hresult, hproc = GetCurrentProcess();
        if (!DuplicateHandle(hproc, hnd, hproc, &hresult, 0, TRUE,
                        DUPLICATE_SAME_ACCESS))
-               die_lasterr("DuplicateHandle(%li) failed", (long) hnd);
+               die_lasterr("DuplicateHandle(%li) failed",
+                       (long) (intptr_t) hnd);
        return hresult;
 }
 
index 86a5eb2571fb282a1d7bad9e6d097b2374b550dc..b95ac3a9cd5ca4fef392a2202f0a5722d15b8dde 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1594,6 +1594,30 @@ int git_config_get_pathname(const char *key, const char **dest)
        return ret;
 }
 
+int git_config_get_untracked_cache(void)
+{
+       int val = -1;
+       const char *v;
+
+       /* Hack for test programs like test-dump-untracked-cache */
+       if (ignore_untracked_cache_config)
+               return -1;
+
+       if (!git_config_get_maybe_bool("core.untrackedcache", &val))
+               return val;
+
+       if (!git_config_get_value("core.untrackedcache", &v)) {
+               if (!strcasecmp(v, "keep"))
+                       return -1;
+
+               error("unknown core.untrackedCache value '%s'; "
+                     "using 'keep' default value", v);
+               return -1;
+       }
+
+       return -1; /* default value */
+}
+
 NORETURN
 void git_die_config_linenr(const char *key, const char *filename, int linenr)
 {
index f34dcaad20d66954c0c13a50bdcbd0f0312cc982..4b2e1b807fc4e6f4467f0da891afe9aa8dad6310 100644 (file)
@@ -518,13 +518,12 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        NO_INET_NTOP = YesPlease
        NO_POSIX_GOODIES = UnfortunatelyYes
        DEFAULT_HELP_FORMAT = html
-       COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -D_USE_32BIT_TIME_T -DNOGDI -Icompat -Icompat/win32
+       COMPAT_CFLAGS += -DNOGDI -Icompat -Icompat/win32
        COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
        COMPAT_OBJS += compat/mingw.o compat/winansi.o \
                compat/win32/pthread.o compat/win32/syslog.o \
                compat/win32/dirent.o
        BASIC_CFLAGS += -DPROTECT_NTFS_DEFAULT=1
-       BASIC_LDFLAGS += -Wl,--large-address-aware
        EXTLIBS += -lws2_32
        GITLIBS += git.res
        PTHREAD_LIBS =
@@ -541,8 +540,34 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
        INTERNAL_QSORT = YesPlease
        HAVE_LIBCHARSET_H = YesPlease
        NO_GETTEXT = YesPlease
+       COMPAT_CLFAGS += -D__USE_MINGW_ACCESS
 else
-       NO_CURL = YesPlease
+       ifeq ($(shell expr "$(uname_R)" : '2\.'),2)
+               # MSys2
+               prefix = /usr/
+               ifeq (MINGW32,$(MSYSTEM))
+                       prefix = /mingw32
+               endif
+               ifeq (MINGW64,$(MSYSTEM))
+                       prefix = /mingw64
+               else
+                       COMPAT_CFLAGS += -D_USE_32BIT_TIME_T
+                       BASIC_LDFLAGS += -Wl,--large-address-aware
+               endif
+               CC = gcc
+               COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO=0
+               INSTALL = /bin/install
+               NO_R_TO_GCC_LINKER = YesPlease
+               INTERNAL_QSORT = YesPlease
+               HAVE_LIBCHARSET_H = YesPlease
+               NO_GETTEXT = YesPlease
+               USE_LIBPCRE= YesPlease
+               NO_CURL =
+               USE_NED_ALLOCATOR = YesPlease
+       else
+               COMPAT_CFLAGS += -D__USE_MINGW_ANSI_STDIO
+               NO_CURL = YesPlease
+       endif
 endif
 endif
 ifeq ($(uname_S),QNX)
index 69568075191af7b22fc4e9e556cdcd3c19dc7a51..45ec47f2b1b45e346290e7bbad143519b1ad91a6 100644 (file)
@@ -1169,7 +1169,7 @@ __git_diff_common_options="--stat --numstat --shortstat --summary
                        --no-prefix --src-prefix= --dst-prefix=
                        --inter-hunk-context=
                        --patience --histogram --minimal
-                       --raw --word-diff
+                       --raw --word-diff --word-diff-regex=
                        --dirstat --dirstat= --dirstat-by-file
                        --dirstat-by-file= --cumulative
                        --diff-algorithm=
@@ -1312,6 +1312,7 @@ _git_grep ()
                        --full-name --line-number
                        --extended-regexp --basic-regexp --fixed-strings
                        --perl-regexp
+                       --threads
                        --files-with-matches --name-only
                        --files-without-match
                        --max-depth
@@ -1687,8 +1688,12 @@ _git_rebase ()
                        --preserve-merges --stat --no-stat
                        --committer-date-is-author-date --ignore-date
                        --ignore-whitespace --whitespace=
-                       --autosquash --fork-point --no-fork-point
-                       --autostash
+                       --autosquash --no-autosquash
+                       --fork-point --no-fork-point
+                       --autostash --no-autostash
+                       --verify --no-verify
+                       --keep-empty --root --force-rebase --no-ff
+                       --exec
                        "
 
                return
@@ -1808,7 +1813,7 @@ _git_config ()
                return
                ;;
        branch.*.rebase)
-               __gitcomp "false true"
+               __gitcomp "false true preserve interactive"
                return
                ;;
        remote.pushdefault)
@@ -2055,6 +2060,7 @@ _git_config ()
                core.sparseCheckout
                core.symlinks
                core.trustctime
+               core.untrackedCache
                core.warnAmbiguousRefs
                core.whitespace
                core.worktree
@@ -2368,7 +2374,7 @@ _git_show_branch ()
        case "$cur" in
        --*)
                __gitcomp "
-                       --all --remotes --topo-order --current --more=
+                       --all --remotes --topo-order --date-order --current --more=
                        --list --independent --merge-base --no-name
                        --color --no-color
                        --sha1-name --sparse --topics --reflog
@@ -2381,7 +2387,7 @@ _git_show_branch ()
 
 _git_stash ()
 {
-       local save_opts='--keep-index --no-keep-index --quiet --patch'
+       local save_opts='--all --keep-index --no-keep-index --quiet --patch --include-untracked'
        local subcommands='save list show apply clear drop pop create branch'
        local subcommand="$(__git_find_on_cmdline "$subcommands")"
        if [ -z "$subcommand" ]; then
@@ -2403,9 +2409,20 @@ _git_stash ()
                apply,--*|pop,--*)
                        __gitcomp "--index --quiet"
                        ;;
-               show,--*|drop,--*|branch,--*)
+               drop,--*)
+                       __gitcomp "--quiet"
+                       ;;
+               show,--*|branch,--*)
+                       ;;
+               branch,*)
+                 if [ $cword -eq 3 ]; then
+                       __gitcomp_nl "$(__git_refs)";
+                       else
+                               __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \
+                                               | sed -n -e 's/:.*//p')"
+                       fi
                        ;;
-               show,*|apply,*|drop,*|pop,*|branch,*)
+               show,*|apply,*|drop,*|pop,*)
                        __gitcomp_nl "$(git --git-dir="$(__gitdir)" stash list \
                                        | sed -n -e 's/:.*//p')"
                        ;;
index 934505bab9e6cf04a3536010ac31b1795c852c9f..86c9cfa0c7a9a6b3b1f9d956084c65164b7b5e4b 100755 (executable)
@@ -574,10 +574,10 @@ then
        if test "$templatefile" != ""
        then
                # Test whether this is just the unaltered template.
-               if cnt=`sed -e '/^#/d' < "$templatefile" |
+               if cnt=$(sed -e '/^#/d' < "$templatefile" |
                        git stripspace |
                        diff "$GIT_DIR"/COMMIT_BAREMSG - |
-                       wc -l` &&
+                       wc -l) &&
                   test 0 -lt $cnt
                then
                        have_commitmsg=t
@@ -630,8 +630,8 @@ then
        fi
        if test -z "$quiet"
        then
-               commit=`git diff-tree --always --shortstat --pretty="format:%h: %s"\
-                      --abbrev --summary --root HEAD --`
+               commit=$(git diff-tree --always --shortstat --pretty="format:%h: %s"\
+                      --abbrev --summary --root HEAD --)
                echo "Created${initial_commit:+ initial} commit $commit"
        fi
 fi
index 554070909cca4d229325a6ca6f401af8bc603cb2..57d2e5616f4702bc94e88b7d61dc886341f7b2cd 100755 (executable)
@@ -146,13 +146,13 @@ esac
 reflist=$(get_remote_refs_for_fetch "$@")
 if test "$tags"
 then
-       taglist=`IFS='  ' &&
+       taglist=$(IFS=' ' &&
                  echo "$ls_remote_result" |
                  git show-ref --exclude-existing=refs/tags/ |
                  while read sha1 name
                  do
                        echo ".${name}:${name}"
-                 done` || exit
+                 done) || exit
        if test "$#" -gt 1
        then
                # remote URL plus explicit refspecs; we need to merge them.
index 52f2aafb9d720723c1dc08e870f38ef495198fa3..ee99f1a4ee89a9e9f358b6cc89fc84cab554b439 100755 (executable)
@@ -523,10 +523,10 @@ do
 
        if test "$exit" -eq 1
        then
-           cnt=`{
+           cnt=$({
                git diff-files --name-only
                git ls-files --unmerged
-           } | wc -l`
+           } | wc -l)
            if test $best_cnt -le 0 || test $cnt -le $best_cnt
            then
                best_strategy=$strategy
index 96e3fed326abeb293e9ef398989bce1054cbf855..672af934431eafcdc84a10230750472ca902ff73 100755 (executable)
@@ -67,8 +67,8 @@ case ",$all_into_one," in
 ,t,)
        args= existing=
        if [ -d "$PACKDIR" ]; then
-               for e in `cd "$PACKDIR" && find . -type f -name '*.pack' \
-                       | sed -e 's/^\.\///' -e 's/\.pack$//'`
+               for e in $(cd "$PACKDIR" && find . -type f -name '*.pack' \
+                       | sed -e 's/^\.\///' -e 's/\.pack$//')
                do
                        if [ -e "$PACKDIR/$e.keep" ]; then
                                : keep
index 7e2aad549103c0c2cdaa452a60a16706f0c7e117..197838d10bfb4881bbecac30a025f1ba7dc44446 100755 (executable)
@@ -138,8 +138,8 @@ cherry-pick)
        }'
 
        logmsg=$(git show -s --pretty=raw --encoding="$encoding" "$commit")
-       set_author_env=`echo "$logmsg" |
-       LANG=C LC_ALL=C sed -ne "$pick_author_script"`
+       set_author_env=$(echo "$logmsg" |
+       LANG=C LC_ALL=C sed -ne "$pick_author_script")
        eval "$set_author_env"
        export GIT_AUTHOR_NAME
        export GIT_AUTHOR_EMAIL
@@ -160,9 +160,9 @@ cherry-pick)
 esac >.msg
 
 eval GITHEAD_$head=HEAD
-eval GITHEAD_$next='`git show -s \
+eval GITHEAD_$next='$(git show -s \
        --pretty=oneline --encoding="$encoding" "$commit" |
-       sed -e "s/^[^ ]* //"`'
+       sed -e "s/^[^ ]* //")'
 export GITHEAD_$head GITHEAD_$next
 
 # This three way merge is an interesting one.  We are at
index 3071baf493442e8bfb3f34252f9c0d13801343b1..6afa9aafdf3b85b44e69aac419d0cd611bb48017 100644 (file)
@@ -37,6 +37,7 @@ GIT_SUBTREE_DOC := git-subtree.1
 GIT_SUBTREE_XML := git-subtree.xml
 GIT_SUBTREE_TXT := git-subtree.txt
 GIT_SUBTREE_HTML := git-subtree.html
+GIT_SUBTREE_TEST := ../../git-subtree
 
 all:: $(GIT_SUBTREE)
 
@@ -71,7 +72,10 @@ $(GIT_SUBTREE_HTML): $(GIT_SUBTREE_TXT)
        $(ASCIIDOC) -b xhtml11 -d manpage -f $(ASCIIDOC_CONF) \
                -agit_version=$(GIT_VERSION) $^
 
-test:
+$(GIT_SUBTREE_TEST): $(GIT_SUBTREE)
+       cp $< $@
+
+test: $(GIT_SUBTREE_TEST)
        $(MAKE) -C t/ test
 
 clean:
index edf36f8c36091551d0a3e6cacb6c91446f0147eb..7a39b30ad09483ef9796d98ca78e52f652046582 100755 (executable)
@@ -245,7 +245,10 @@ find_latest_squash()
                case "$a" in
                        START) sq="$b" ;;
                        git-subtree-mainline:) main="$b" ;;
-                       git-subtree-split:) sub="$b" ;;
+                       git-subtree-split:)
+                               sub="$(git rev-parse "$b^0")" ||
+                                   die "could not rev-parse split hash $b from commit $sq"
+                               ;;
                        END)
                                if [ -n "$sub" ]; then
                                        if [ -n "$main" ]; then
@@ -278,7 +281,10 @@ find_existing_splits()
                case "$a" in
                        START) sq="$b" ;;
                        git-subtree-mainline:) main="$b" ;;
-                       git-subtree-split:) sub="$b" ;;
+                       git-subtree-split:)
+                               sub="$(git rev-parse "$b^0")" ||
+                                   die "could not rev-parse split hash $b from commit $sq"
+                               ;;
                        END)
                                debug "  Main is: '$main'"
                                if [ -z "$main" -a -n "$sub" ]; then
@@ -479,8 +485,16 @@ copy_or_skip()
                        p="$p -p $parent"
                fi
        done
-       
-       if [ -n "$identical" ]; then
+
+       copycommit=
+       if [ -n "$identical" ] && [ -n "$nonidentical" ]; then
+               extras=$(git rev-list --count $identical..$nonidentical)
+               if [ "$extras" -ne 0 ]; then
+                       # we need to preserve history along the other branch
+                       copycommit=1
+               fi
+       fi
+       if [ -n "$identical" ] && [ -z "$copycommit" ]; then
                echo $identical
        else
                copy_commit $rev $tree "$p" || exit $?
index 751aee3a0cd782c9eb1f98cb78f582011fb0b181..3bf96a9bb6b29757736d8f4250fae25664e298f0 100755 (executable)
@@ -1014,4 +1014,64 @@ test_expect_success 'push split to subproj' '
        )
 '
 
+#
+# This test covers 2 cases in subtree split copy_or_skip code
+# 1) Merges where one parent is a superset of the changes of the other
+#    parent regarding changes to the subtree, in this case the merge
+#    commit should be copied
+# 2) Merges where only one parent operate on the subtree, and the merge
+#    commit should be skipped
+#
+# (1) is checked by ensuring subtree_tip is a descendent of subtree_branch
+# (2) should have a check added (not_a_subtree_change shouldn't be present
+#     on the produced subtree)
+#
+# Other related cases which are not tested (or currently handled correctly)
+# - Case (1) where there are more than 2 parents, it will sometimes correctly copy
+#   the merge, and sometimes not
+# - Merge commit where both parents have same tree as the merge, currently
+#   will always be skipped, even if they reached that state via different
+#   set of commits.
+#
+
+next_test
+test_expect_success 'subtree descendant check' '
+       subtree_test_create_repo "$subtree_test_count" &&
+       test_create_commit "$subtree_test_count" folder_subtree/a &&
+       (
+               cd "$subtree_test_count" &&
+               git branch branch
+       ) &&
+       test_create_commit "$subtree_test_count" folder_subtree/0 &&
+       test_create_commit "$subtree_test_count" folder_subtree/b &&
+       cherry=$(cd "$subtree_test_count"; git rev-parse HEAD) &&
+       (
+               cd "$subtree_test_count" &&
+               git checkout branch
+       ) &&
+       test_create_commit "$subtree_test_count" commit_on_branch &&
+       (
+               cd "$subtree_test_count" &&
+               git cherry-pick $cherry &&
+               git checkout master &&
+               git merge -m "merge should be kept on subtree" branch &&
+               git branch no_subtree_work_branch
+       ) &&
+       test_create_commit "$subtree_test_count" folder_subtree/d &&
+       (
+               cd "$subtree_test_count" &&
+               git checkout no_subtree_work_branch
+       ) &&
+       test_create_commit "$subtree_test_count" not_a_subtree_change &&
+       (
+               cd "$subtree_test_count" &&
+               git checkout master &&
+               git merge -m "merge should be skipped on subtree" no_subtree_work_branch &&
+
+               git subtree split --prefix folder_subtree/ --branch subtree_tip master &&
+               git subtree split --prefix folder_subtree/ --branch subtree_branch branch &&
+               check_equal $(git rev-list --count subtree_tip..subtree_branch) 0
+       )
+'
+
 test_done
index 8dc73ece15a075bb60971da577d2da272c8f7c14..1053872eea903cc07d10cd18a3d45874f6eaf7bf 100755 (executable)
@@ -31,8 +31,8 @@ BODY=$(sed -e "1,/${SEP}/d" $1)
 CMT_MSG=$(sed -e '1,/^$/d' -e '/^---$/,$d' "${PATCH}")
 DIFF=$(sed -e '1,/^---$/d' "${PATCH}")
 
-CCS=`echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \
-       -e 's/^Signed-off-by: \(.*\)/\1,/gp'`
+CCS=$(echo -e "$CMT_MSG\n$HEADERS" | sed -n -e 's/^Cc: \(.*\)$/\1,/gp' \
+       -e 's/^Signed-off-by: \(.*\)/\1,/gp')
 
 echo "$SUBJECT" > $1
 echo "Cc: $CCS" >> $1
index 02d5f1e23c841accfbb7acfbc992ab85dbb6645f..8cd6222a263ac99a63335bf7080a3fb4dd797ff7 100644 (file)
--- a/convert.c
+++ b/convert.c
  * translation when the "text" attribute or "auto_crlf" option is set.
  */
 
+/* Stat bits: When BIN is set, the txt bits are unset */
+#define CONVERT_STAT_BITS_TXT_LF    0x1
+#define CONVERT_STAT_BITS_TXT_CRLF  0x2
+#define CONVERT_STAT_BITS_BIN       0x4
+
 enum crlf_action {
        CRLF_GUESS = -1,
        CRLF_BINARY = 0,
@@ -75,26 +80,75 @@ static void gather_stats(const char *buf, unsigned long size, struct text_stat *
 
 /*
  * The same heuristics as diff.c::mmfile_is_binary()
+ * We treat files with bare CR as binary
  */
-static int is_binary(unsigned long size, struct text_stat *stats)
+static int convert_is_binary(unsigned long size, const struct text_stat *stats)
 {
-
+       if (stats->cr != stats->crlf)
+               return 1;
        if (stats->nul)
                return 1;
        if ((stats->printable >> 7) < stats->nonprintable)
                return 1;
-       /*
-        * Other heuristics? Average line length might be relevant,
-        * as might LF vs CR vs CRLF counts..
-        *
-        * NOTE! It might be normal to have a low ratio of CRLF to LF
-        * (somebody starts with a LF-only file and edits it with an editor
-        * that adds CRLF only to lines that are added..). But do  we
-        * want to support CR-only? Probably not.
-        */
        return 0;
 }
 
+static unsigned int gather_convert_stats(const char *data, unsigned long size)
+{
+       struct text_stat stats;
+       if (!data || !size)
+               return 0;
+       gather_stats(data, size, &stats);
+       if (convert_is_binary(size, &stats))
+               return CONVERT_STAT_BITS_BIN;
+       else if (stats.crlf && stats.crlf == stats.lf)
+               return CONVERT_STAT_BITS_TXT_CRLF;
+       else if (stats.crlf && stats.lf)
+               return CONVERT_STAT_BITS_TXT_CRLF | CONVERT_STAT_BITS_TXT_LF;
+       else if (stats.lf)
+               return CONVERT_STAT_BITS_TXT_LF;
+       else
+               return 0;
+}
+
+static const char *gather_convert_stats_ascii(const char *data, unsigned long size)
+{
+       unsigned int convert_stats = gather_convert_stats(data, size);
+
+       if (convert_stats & CONVERT_STAT_BITS_BIN)
+               return "-text";
+       switch (convert_stats) {
+       case CONVERT_STAT_BITS_TXT_LF:
+               return "lf";
+       case CONVERT_STAT_BITS_TXT_CRLF:
+               return "crlf";
+       case CONVERT_STAT_BITS_TXT_LF | CONVERT_STAT_BITS_TXT_CRLF:
+               return "mixed";
+       default:
+               return "none";
+       }
+}
+
+const char *get_cached_convert_stats_ascii(const char *path)
+{
+       const char *ret;
+       unsigned long sz;
+       void *data = read_blob_data_from_cache(path, &sz);
+       ret = gather_convert_stats_ascii(data, sz);
+       free(data);
+       return ret;
+}
+
+const char *get_wt_convert_stats_ascii(const char *path)
+{
+       const char *ret = "";
+       struct strbuf sb = STRBUF_INIT;
+       if (strbuf_read_file(&sb, path, 0) >= 0)
+               ret = gather_convert_stats_ascii(sb.buf, sb.len);
+       strbuf_release(&sb);
+       return ret;
+}
+
 static enum eol output_eol(enum crlf_action crlf_action)
 {
        switch (crlf_action) {
@@ -187,18 +241,7 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
        gather_stats(src, len, &stats);
 
        if (crlf_action == CRLF_AUTO || crlf_action == CRLF_GUESS) {
-               /*
-                * We're currently not going to even try to convert stuff
-                * that has bare CR characters. Does anybody do that crazy
-                * stuff?
-                */
-               if (stats.cr != stats.crlf)
-                       return 0;
-
-               /*
-                * And add some heuristics for binary vs text, of course...
-                */
-               if (is_binary(len, &stats))
+               if (convert_is_binary(len, &stats))
                        return 0;
 
                if (crlf_action == CRLF_GUESS) {
@@ -277,11 +320,7 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,
                                return 0;
                }
 
-               /* If we have any bare CR characters, we're not going to touch it */
-               if (stats.cr != stats.crlf)
-                       return 0;
-
-               if (is_binary(len, &stats))
+               if (convert_is_binary(len, &stats))
                        return 0;
        }
 
@@ -777,6 +816,30 @@ int would_convert_to_git_filter_fd(const char *path)
        return apply_filter(path, NULL, 0, -1, NULL, ca.drv->clean);
 }
 
+const char *get_convert_attr_ascii(const char *path)
+{
+       struct conv_attrs ca;
+       enum crlf_action crlf_action;
+
+       convert_attrs(&ca, path);
+       crlf_action = input_crlf_action(ca.crlf_action, ca.eol_attr);
+       switch (crlf_action) {
+       case CRLF_GUESS:
+               return "";
+       case CRLF_BINARY:
+               return "-text";
+       case CRLF_TEXT:
+               return "text";
+       case CRLF_INPUT:
+               return "text eol=lf";
+       case CRLF_CRLF:
+               return "text=auto eol=crlf";
+       case CRLF_AUTO:
+               return "text=auto";
+       }
+       return "";
+}
+
 int convert_to_git(const char *path, const char *src, size_t len,
                    struct strbuf *dst, enum safe_crlf checksafe)
 {
index d9d853cd3d2f6d94965a2c2fc8e587386402a83b..ccf436bfbf2a89ceb7003ea6dbebf6ae2b6f4a8c 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -32,6 +32,9 @@ enum eol {
 };
 
 extern enum eol core_eol;
+extern const char *get_cached_convert_stats_ascii(const char *path);
+extern const char *get_wt_convert_stats_ascii(const char *path);
+extern const char *get_convert_attr_ascii(const char *path);
 
 /* returns 1 if *dst was used */
 extern int convert_to_git(const char *path, const char *src, size_t len,
index 9365f2ce5c188d86b1b60029e4549e1bd844214f..cc65a9c0d342aa51d4b307fe10c626d940e2f211 100644 (file)
@@ -96,12 +96,12 @@ static int read_request(FILE *fh, struct credential *c,
        static struct strbuf item = STRBUF_INIT;
        const char *p;
 
-       strbuf_getline(&item, fh, '\n');
+       strbuf_getline_lf(&item, fh);
        if (!skip_prefix(item.buf, "action=", &p))
                return error("client sent bogus action line: %s", item.buf);
        strbuf_addstr(action, p);
 
-       strbuf_getline(&item, fh, '\n');
+       strbuf_getline_lf(&item, fh);
        if (!skip_prefix(item.buf, "timeout=", &p))
                return error("client sent bogus timeout line: %s", item.buf);
        *timeout = atoi(p);
index 54c4e047373757598f6de7bf994251f0169b2b38..57141679abdaa804282a0cc2d808e7c6687d924a 100644 (file)
@@ -23,7 +23,7 @@ static int parse_credential_file(const char *fn,
                return found_credential;
        }
 
-       while (strbuf_getline(&line, fh, '\n') != EOF) {
+       while (strbuf_getline_lf(&line, fh) != EOF) {
                credential_from_url(&entry, line.buf);
                if (entry.username && entry.password &&
                    credential_match(c, &entry)) {
index b146ad8481b133892a542691c7e36f5e7974cfdc..7d6501d190a529933d501e7f7006a70c4897282b 100644 (file)
@@ -142,7 +142,7 @@ int credential_read(struct credential *c, FILE *fp)
 {
        struct strbuf line = STRBUF_INIT;
 
-       while (strbuf_getline(&line, fp, '\n') != EOF) {
+       while (strbuf_getline_lf(&line, fp) != EOF) {
                char *key = line.buf;
                char *value = strchr(key, '=');
 
index be70cd4da09ccab8850be41e19b0fc4b9a10f502..46b411c7d941ecf862b7a7ffdce38ef8767e29e4 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -424,7 +424,7 @@ static void copy_to_log(int fd)
                return;
        }
 
-       while (strbuf_getline(&line, fp, '\n') != EOF) {
+       while (strbuf_getline_lf(&line, fp) != EOF) {
                logerror("%s", line.buf);
                strbuf_setlen(&line, 0);
        }
index 8e0fd270b5be4d9ab8616ab57202862dd2fc6eda..03daadb25af835a695c7d0baf466b0e1f82b58c4 100644 (file)
@@ -237,12 +237,12 @@ static void fixup_paths(const char **path, struct strbuf *replacement)
 }
 
 void diff_no_index(struct rev_info *revs,
-                  int argc, const char **argv,
-                  const char *prefix)
+                  int argc, const char **argv)
 {
        int i, prefixlen;
        const char *paths[2];
        struct strbuf replacement = STRBUF_INIT;
+       const char *prefix = revs->prefix;
 
        diff_setup(&revs->diffopt);
        for (i = 1; i < argc - 2; ) {
@@ -252,7 +252,8 @@ void diff_no_index(struct rev_info *revs,
                else if (!strcmp(argv[i], "--"))
                        i++;
                else {
-                       j = diff_opt_parse(&revs->diffopt, argv + i, argc - i);
+                       j = diff_opt_parse(&revs->diffopt, argv + i, argc - i,
+                                          revs->prefix);
                        if (j <= 0)
                                die("invalid diff option/value: %s", argv[i]);
                        i += j;
diff --git a/diff.c b/diff.c
index 80eb0c2156a0f3727f8a9598f3e83233224539b0..2136b6970b3a9751a3ec420bac61e9baa08df9b0 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -3693,12 +3693,16 @@ static int parse_ws_error_highlight(struct diff_options *opt, const char *arg)
        return 1;
 }
 
-int diff_opt_parse(struct diff_options *options, const char **av, int ac)
+int diff_opt_parse(struct diff_options *options,
+                  const char **av, int ac, const char *prefix)
 {
        const char *arg = av[0];
        const char *optarg;
        int argcount;
 
+       if (!prefix)
+               prefix = "";
+
        /* Output format options */
        if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch")
            || opt_arg(arg, 'U', "unified", &options->context))
@@ -3915,7 +3919,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        else if (!strcmp(arg, "--pickaxe-regex"))
                options->pickaxe_opts |= DIFF_PICKAXE_REGEX;
        else if ((argcount = short_opt('O', av, &optarg))) {
-               options->orderfile = optarg;
+               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               options->orderfile = xstrdup(path);
                return argcount;
        }
        else if ((argcount = parse_long_opt("diff-filter", av, &optarg))) {
@@ -3954,9 +3959,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        else if (!strcmp(arg, "--no-function-context"))
                DIFF_OPT_CLR(options, FUNCCONTEXT);
        else if ((argcount = parse_long_opt("output", av, &optarg))) {
-               options->file = fopen(optarg, "w");
+               const char *path = prefix_filename(prefix, strlen(prefix), optarg);
+               options->file = fopen(path, "w");
                if (!options->file)
-                       die_errno("Could not open '%s'", optarg);
+                       die_errno("Could not open '%s'", path);
                options->close_file = 1;
                return argcount;
        } else
diff --git a/diff.h b/diff.h
index f7208ad103d4b81194e5b14e7e027a2d25388667..70b2d70d64e1e47da617f51b8385870a22e92f40 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -91,7 +91,7 @@ typedef struct strbuf *(*diff_prefix_fn_t)(struct diff_options *opt, void *data)
 #define DIFF_OPT_DIRSTAT_BY_LINE     (1 << 28)
 #define DIFF_OPT_FUNCCONTEXT         (1 << 29)
 #define DIFF_OPT_PICKAXE_IGNORE_CASE (1 << 30)
-#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1 << 31)
+#define DIFF_OPT_DEFAULT_FOLLOW_RENAMES (1U << 31)
 
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_TOUCHED(opts, flag)    ((opts)->touched_flags & DIFF_OPT_##flag)
@@ -268,7 +268,7 @@ extern int parse_long_opt(const char *opt, const char **argv,
 extern int git_diff_basic_config(const char *var, const char *value, void *cb);
 extern int git_diff_ui_config(const char *var, const char *value, void *cb);
 extern void diff_setup(struct diff_options *);
-extern int diff_opt_parse(struct diff_options *, const char **, int);
+extern int diff_opt_parse(struct diff_options *, const char **, int, const char *);
 extern void diff_setup_done(struct diff_options *);
 
 #define DIFF_DETECT_RENAME     1
@@ -345,7 +345,7 @@ extern int diff_flush_patch_id(struct diff_options *, unsigned char *);
 
 extern int diff_result_code(struct diff_options *, int);
 
-extern void diff_no_index(struct rev_info *, int, const char **, const char *);
+extern void diff_no_index(struct rev_info *, int, const char **);
 
 extern int index_differs_from(const char *def, int diff_flags);
 
diff --git a/dir.c b/dir.c
index d2a8f06b0243bda92c04f57d96c0b18838ee7dce..f0b6d0a3eab704311ed2c93a3da5db0683b3125c 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -564,9 +564,7 @@ void clear_exclude_list(struct exclude_list *el)
        free(el->excludes);
        free(el->filebuf);
 
-       el->nr = 0;
-       el->excludes = NULL;
-       el->filebuf = NULL;
+       memset(el, 0, sizeof(*el));
 }
 
 static void trim_trailing_spaces(char *buf)
@@ -882,25 +880,6 @@ int match_pathname(const char *pathname, int pathlen,
                 */
                if (!patternlen && !namelen)
                        return 1;
-               /*
-                * This can happen when we ignore some exclude rules
-                * on directories in other to see if negative rules
-                * may match. E.g.
-                *
-                * /abc
-                * !/abc/def/ghi
-                *
-                * The pattern of interest is "/abc". On the first
-                * try, we should match path "abc" with this pattern
-                * in the "if" statement right above, but the caller
-                * ignores it.
-                *
-                * On the second try with paths within "abc",
-                * e.g. "abc/xyz", we come here and try to match it
-                * with "/abc".
-                */
-               if (!patternlen && namelen && *name == '/')
-                       return 1;
        }
 
        return fnmatch_icase_mem(pattern, patternlen,
@@ -908,48 +887,6 @@ int match_pathname(const char *pathname, int pathlen,
                                 WM_PATHNAME) == 0;
 }
 
-/*
- * Return non-zero if pathname is a directory and an ancestor of the
- * literal path in a (negative) pattern. This is used to keep
- * descending in "foo" and "foo/bar" when the pattern is
- * "!foo/bar/.gitignore". "foo/notbar" will not be descended however.
- */
-static int match_neg_path(const char *pathname, int pathlen, int *dtype,
-                         const char *base, int baselen,
-                         const char *pattern, int prefix, int patternlen,
-                         int flags)
-{
-       assert((flags & EXC_FLAG_NEGATIVE) && !(flags & EXC_FLAG_NODIR));
-
-       if (*dtype == DT_UNKNOWN)
-               *dtype = get_dtype(NULL, pathname, pathlen);
-       if (*dtype != DT_DIR)
-               return 0;
-
-       if (*pattern == '/') {
-               pattern++;
-               patternlen--;
-               prefix--;
-       }
-
-       if (baselen) {
-               if (((pathlen < baselen && base[pathlen] == '/') ||
-                    pathlen == baselen) &&
-                   !strncmp_icase(pathname, base, pathlen))
-                       return 1;
-               pathname += baselen + 1;
-               pathlen  -= baselen + 1;
-       }
-
-
-       if (prefix &&
-           ((pathlen < prefix && pattern[pathlen] == '/') &&
-            !strncmp_icase(pathname, pattern, pathlen)))
-               return 1;
-
-       return 0;
-}
-
 /*
  * Scan the given exclude list in reverse to see whether pathname
  * should be ignored.  The first match (i.e. the last on the list), if
@@ -963,7 +900,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
                                                       struct exclude_list *el)
 {
        struct exclude *exc = NULL; /* undecided */
-       int i, matched_negative_path = 0;
+       int i;
 
        if (!el->nr)
                return NULL;    /* undefined */
@@ -998,18 +935,7 @@ static struct exclude *last_exclude_matching_from_list(const char *pathname,
                        exc = x;
                        break;
                }
-
-               if ((x->flags & EXC_FLAG_NEGATIVE) && !matched_negative_path &&
-                   match_neg_path(pathname, pathlen, dtype, x->base,
-                                  x->baselen ? x->baselen - 1 : 0,
-                                  exclude, prefix, x->patternlen, x->flags))
-                       matched_negative_path = 1;
-       }
-       if (exc &&
-           !(exc->flags & EXC_FLAG_NEGATIVE) &&
-           !(exc->flags & EXC_FLAG_NODIR) &&
-           matched_negative_path)
-               exc = NULL;
+       }
        return exc;
 }
 
@@ -1913,31 +1839,67 @@ static const char *get_ident_string(void)
                return sb.buf;
        if (uname(&uts) < 0)
                die_errno(_("failed to get kernel name and information"));
-       strbuf_addf(&sb, "Location %s, system %s %s %s", get_git_work_tree(),
-                   uts.sysname, uts.release, uts.version);
+       strbuf_addf(&sb, "Location %s, system %s", get_git_work_tree(),
+                   uts.sysname);
        return sb.buf;
 }
 
 static int ident_in_untracked(const struct untracked_cache *uc)
 {
-       const char *end = uc->ident.buf + uc->ident.len;
-       const char *p   = uc->ident.buf;
+       /*
+        * Previous git versions may have saved many NUL separated
+        * strings in the "ident" field, but it is insane to manage
+        * many locations, so just take care of the first one.
+        */
 
-       for (p = uc->ident.buf; p < end; p += strlen(p) + 1)
-               if (!strcmp(p, get_ident_string()))
-                       return 1;
-       return 0;
+       return !strcmp(uc->ident.buf, get_ident_string());
 }
 
-void add_untracked_ident(struct untracked_cache *uc)
+static void set_untracked_ident(struct untracked_cache *uc)
 {
-       if (ident_in_untracked(uc))
-               return;
+       strbuf_reset(&uc->ident);
        strbuf_addstr(&uc->ident, get_ident_string());
-       /* this strbuf contains a list of strings, save NUL too */
+
+       /*
+        * This strbuf used to contain a list of NUL separated
+        * strings, so save NUL too for backward compatibility.
+        */
        strbuf_addch(&uc->ident, 0);
 }
 
+static void new_untracked_cache(struct index_state *istate)
+{
+       struct untracked_cache *uc = xcalloc(1, sizeof(*uc));
+       strbuf_init(&uc->ident, 100);
+       uc->exclude_per_dir = ".gitignore";
+       /* should be the same flags used by git-status */
+       uc->dir_flags = DIR_SHOW_OTHER_DIRECTORIES | DIR_HIDE_EMPTY_DIRECTORIES;
+       set_untracked_ident(uc);
+       istate->untracked = uc;
+       istate->cache_changed |= UNTRACKED_CHANGED;
+}
+
+void add_untracked_cache(struct index_state *istate)
+{
+       if (!istate->untracked) {
+               new_untracked_cache(istate);
+       } else {
+               if (!ident_in_untracked(istate->untracked)) {
+                       free_untracked_cache(istate->untracked);
+                       new_untracked_cache(istate);
+               }
+       }
+}
+
+void remove_untracked_cache(struct index_state *istate)
+{
+       if (istate->untracked) {
+               free_untracked_cache(istate->untracked);
+               istate->untracked = NULL;
+               istate->cache_changed |= UNTRACKED_CHANGED;
+       }
+}
+
 static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *dir,
                                                      int base_len,
                                                      const struct pathspec *pathspec)
@@ -1995,7 +1957,7 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d
                return NULL;
 
        if (!ident_in_untracked(dir->untracked)) {
-               warning(_("Untracked cache is disabled on this system."));
+               warning(_("Untracked cache is disabled on this system or location."));
                return NULL;
        }
 
diff --git a/dir.h b/dir.h
index 7b5855dd80eda02973a55c827d79826a25937880..cd46f30017ce239720926afdad4301b2ac402ccf 100644 (file)
--- a/dir.h
+++ b/dir.h
@@ -307,5 +307,6 @@ void untracked_cache_add_to_index(struct index_state *, const char *);
 void free_untracked_cache(struct untracked_cache *);
 struct untracked_cache *read_untracked_extension(const void *data, unsigned long sz);
 void write_untracked_extension(struct strbuf *out, struct untracked_cache *untracked);
-void add_untracked_ident(struct untracked_cache *);
+void add_untracked_cache(struct index_state *istate);
+void remove_untracked_cache(struct index_state *istate);
 #endif
index 2da7fe2e06ff38b977209d44b7404c93358430af..6dec9d0403f11579a7ab316db87a1dbbc58e71b2 100644 (file)
@@ -87,6 +87,13 @@ int auto_comment_line_char;
 /* Parallel index stat data preload? */
 int core_preload_index = 1;
 
+/*
+ * This is a hack for test programs like test-dump-untracked-cache to
+ * ensure that they do not modify the untracked cache when reading it.
+ * Do not use it otherwise!
+ */
+int ignore_untracked_cache_config;
+
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
 char *git_work_tree_cfg;
 static char *work_tree;
@@ -235,8 +242,6 @@ void set_git_work_tree(const char *new_work_tree)
        }
        git_work_tree_initialized = 1;
        work_tree = xstrdup(real_path(new_work_tree));
-       if (setenv(GIT_WORK_TREE_ENVIRONMENT, work_tree, 1))
-               die("could not set GIT_WORK_TREE to '%s'", work_tree);
 }
 
 const char *get_git_work_tree(void)
index 3c65edb5c44e1fa57beef851d56a9674a5be1b72..bf01b3422142d6be204a983a9909efdb29d385d0 100644 (file)
@@ -1888,7 +1888,7 @@ static int read_next_command(void)
                        struct recent_command *rc;
 
                        strbuf_detach(&command_buf, NULL);
-                       stdin_eof = strbuf_getline(&command_buf, stdin, '\n');
+                       stdin_eof = strbuf_getline_lf(&command_buf, stdin);
                        if (stdin_eof)
                                return EOF;
 
@@ -1960,7 +1960,7 @@ static int parse_data(struct strbuf *sb, uintmax_t limit, uintmax_t *len_res)
 
                strbuf_detach(&command_buf, NULL);
                for (;;) {
-                       if (strbuf_getline(&command_buf, stdin, '\n') == EOF)
+                       if (strbuf_getline_lf(&command_buf, stdin) == EOF)
                                die("EOF in data (terminator '%s' not found)", term);
                        if (term_len == command_buf.len
                                && !strcmp(term, command_buf.buf))
index 2da0a75a380da198bd65fe3d9b0c95ef98a0b4aa..693a336ff52ffc5acfaaa114829008de21b0a651 100644 (file)
@@ -253,6 +253,8 @@ struct itimerval {
 #else
 #define basename gitbasename
 extern char *gitbasename(char *);
+#define dirname gitdirname
+extern char *gitdirname(char *);
 #endif
 
 #ifndef NO_ICONV
@@ -335,6 +337,14 @@ static inline int git_has_dos_drive_prefix(const char *path)
 #define has_dos_drive_prefix git_has_dos_drive_prefix
 #endif
 
+#ifndef skip_dos_drive_prefix
+static inline int git_skip_dos_drive_prefix(char **path)
+{
+       return 0;
+}
+#define skip_dos_drive_prefix git_skip_dos_drive_prefix
+#endif
+
 #ifndef is_dir_sep
 static inline int git_is_dir_sep(int c)
 {
@@ -733,6 +743,7 @@ extern int xmkstemp_mode(char *template, int mode);
 extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
 extern int odb_pack_keep(char *name, size_t namesz, const unsigned char *sha1);
 extern char *xgetcwd(void);
+extern FILE *fopen_for_writing(const char *path);
 
 #define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), (alloc) * sizeof(*(x)))
 
index 98f1779cf3241fa12300fbf3dc0c4eff8ab10b61..86b2ff1e07614846465109dcb4b9afed11013839 100755 (executable)
@@ -404,7 +404,7 @@ while read commit parents; do
        then
                tree=$(git write-tree)
        else
-               tree="$commit^{tree}"
+               tree=$(git rev-parse "$commit^{tree}")
        fi
        workdir=$workdir @SHELL_PATH@ -c "$filter_commit" "git commit-tree" \
                "$tree" $parentstr < ../message > ../map/$commit ||
index 49bf7c5365130ec290948ee8abba28d757774381..8249915d3c6c974df906a2c99c1d172d50bab502 100755 (executable)
@@ -11,7 +11,7 @@
 if [ $# -eq 0 ]
 then
        cat <<!
-Usage: `basename $0` git-gui-glossary.txt > git-gui-glossary.pot
+Usage: $(basename $0) git-gui-glossary.txt > git-gui-glossary.pot
 !
        exit 1;
 fi
@@ -33,7 +33,7 @@ cat <<!
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: `date +'%Y-%m-%d %H:%M%z'`\n"
+"POT-Creation-Date: $(date +'%Y-%m-%d %H:%M%z')\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
index c33dece5d29ebf59fa0b78a9fda2de48114b1fe3..825b9f32d5540ab1f8d373fff2d3bf79caabee00 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -253,8 +253,8 @@ def p4_add(f):
 def p4_delete(f):
     p4_system(["delete", wildcard_encode(f)])
 
-def p4_edit(f):
-    p4_system(["edit"wildcard_encode(f)])
+def p4_edit(f, *options):
+    p4_system(["edit"] + list(options) + [wildcard_encode(f)])
 
 def p4_revert(f):
     p4_system(["revert", wildcard_encode(f)])
@@ -1554,6 +1554,7 @@ def applyCommit(self, id):
 
         diff = read_pipe_lines("git diff-tree -r %s \"%s^\" \"%s\"" % (self.diffOpts, id, id))
         filesToAdd = set()
+        filesToChangeType = set()
         filesToDelete = set()
         editedFiles = set()
         pureRenameCopy = set()
@@ -1614,6 +1615,8 @@ def applyCommit(self, id):
                     os.unlink(dest)
                     filesToDelete.add(src)
                 editedFiles.add(dest)
+            elif modifier == "T":
+                filesToChangeType.add(path)
             else:
                 die("unknown modifier %s for %s" % (modifier, path))
 
@@ -1673,6 +1676,8 @@ def applyCommit(self, id):
         #
         system(applyPatchCmd)
 
+        for f in filesToChangeType:
+            p4_edit(f, "-t", "auto")
         for f in filesToAdd:
             p4_add(f)
         for f in filesToDelete:
index af7ba5fd90c3000892ed31893e1812514e4f3773..cf60c4390870ef28cff08b6a173a435d41e2d470 100755 (executable)
@@ -176,7 +176,7 @@ You can run "git stash pop" or "git stash drop" at any time.
 
 finish_rebase () {
        apply_autostash &&
-       git gc --auto &&
+       { git gc --auto || true; } &&
        rm -rf "$state_dir"
 }
 
index 6caa5b563fafb09cee5eb8f35283e7b9fa967439..d356901348042a7f2ec67211857e4d551d169d52 100755 (executable)
@@ -524,8 +524,13 @@ sub parse_sendmail_aliases {
                if (/^\s*alias\s+(?:-group\s+\S+\s+)*(\S+)\s+(.*)$/) {
                        my ($alias, $addr) = ($1, $2);
                        $addr =~ s/#.*$//; # mutt allows # comments
-                        # commas delimit multiple addresses
-                       $aliases{$alias} = [ split_addrs($addr) ];
+                       # commas delimit multiple addresses
+                       my @addr = split_addrs($addr);
+
+                       # quotes may be escaped in the file,
+                       # unescape them so we do not double-escape them later.
+                       s/\\"/"/g foreach @addr;
+                       $aliases{$alias} = \@addr
                }}},
        mailrc => sub { my $fh = shift; while (<$fh>) {
                if (/^alias\s+(\S+)\s+(.*)$/) {
diff --git a/git.c b/git.c
index 6ed824cacfccddcb01104835b45ab934ff3f443e..da278c3d41ed308581ffec46e3487e7670898d41 100644 (file)
--- a/git.c
+++ b/git.c
@@ -25,14 +25,14 @@ static const char *env_names[] = {
        GIT_PREFIX_ENVIRONMENT
 };
 static char *orig_env[4];
-static int saved_environment;
+static int saved_env_before_alias;
 
-static void save_env(void)
+static void save_env_before_alias(void)
 {
        int i;
-       if (saved_environment)
+       if (saved_env_before_alias)
                return;
-       saved_environment = 1;
+       saved_env_before_alias = 1;
        orig_cwd = xgetcwd();
        for (i = 0; i < ARRAY_SIZE(env_names); i++) {
                orig_env[i] = getenv(env_names[i]);
@@ -41,13 +41,16 @@ static void save_env(void)
        }
 }
 
-static void restore_env(void)
+static void restore_env(int external_alias)
 {
        int i;
-       if (orig_cwd && chdir(orig_cwd))
+       if (!external_alias && orig_cwd && chdir(orig_cwd))
                die_errno("could not move to %s", orig_cwd);
        free(orig_cwd);
        for (i = 0; i < ARRAY_SIZE(env_names); i++) {
+               if (external_alias &&
+                   !strcmp(env_names[i], GIT_PREFIX_ENVIRONMENT))
+                       continue;
                if (orig_env[i])
                        setenv(env_names[i], orig_env[i], 1);
                else
@@ -226,14 +229,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 static int handle_alias(int *argcp, const char ***argv)
 {
        int envchanged = 0, ret = 0, saved_errno = errno;
-       const char *subdir;
        int count, option_count;
        const char **new_argv;
        const char *alias_command;
        char *alias_string;
        int unused_nongit;
 
-       subdir = setup_git_directory_gently(&unused_nongit);
+       save_env_before_alias();
+       setup_git_directory_gently(&unused_nongit);
 
        alias_command = (*argv)[0];
        alias_string = alias_lookup(alias_command);
@@ -243,6 +246,7 @@ static int handle_alias(int *argcp, const char ***argv)
                        int argc = *argcp, i;
 
                        commit_pager_choice();
+                       restore_env(1);
 
                        /* build alias_argv */
                        alias_argv = xmalloc(sizeof(*alias_argv) * (argc + 1));
@@ -291,8 +295,7 @@ static int handle_alias(int *argcp, const char ***argv)
                ret = 1;
        }
 
-       if (subdir && chdir(subdir))
-               die_errno("Cannot change to '%s'", subdir);
+       restore_env(0);
 
        errno = saved_errno;
 
@@ -307,7 +310,6 @@ static int handle_alias(int *argcp, const char ***argv)
  * RUN_SETUP for reading from the configuration file.
  */
 #define NEED_WORK_TREE         (1<<3)
-#define NO_SETUP               (1<<4)
 
 struct cmd_struct {
        const char *cmd;
@@ -389,7 +391,7 @@ static struct cmd_struct commands[] = {
        { "cherry", cmd_cherry, RUN_SETUP },
        { "cherry-pick", cmd_cherry_pick, RUN_SETUP | NEED_WORK_TREE },
        { "clean", cmd_clean, RUN_SETUP | NEED_WORK_TREE },
-       { "clone", cmd_clone, NO_SETUP },
+       { "clone", cmd_clone },
        { "column", cmd_column, RUN_SETUP_GENTLY },
        { "commit", cmd_commit, RUN_SETUP | NEED_WORK_TREE },
        { "commit-tree", cmd_commit_tree, RUN_SETUP },
@@ -415,8 +417,8 @@ static struct cmd_struct commands[] = {
        { "hash-object", cmd_hash_object },
        { "help", cmd_help },
        { "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
-       { "init", cmd_init_db, NO_SETUP },
-       { "init-db", cmd_init_db, NO_SETUP },
+       { "init", cmd_init_db },
+       { "init-db", cmd_init_db },
        { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP_GENTLY },
        { "log", cmd_log, RUN_SETUP },
        { "ls-files", cmd_ls_files, RUN_SETUP },
@@ -530,9 +532,13 @@ static void handle_builtin(int argc, const char **argv)
 
        builtin = get_builtin(cmd);
        if (builtin) {
-               if (saved_environment && (builtin->option & NO_SETUP))
-                       restore_env();
-               else
+               /*
+                * XXX: if we can figure out cases where it is _safe_
+                * to do, we can avoid spawning a new process when
+                * saved_env_before_alias is true
+                * (i.e. setup_git_dir* has been run once)
+                */
+               if (!saved_env_before_alias)
                        exit(run_builtin(builtin, argc, argv));
        }
 }
@@ -590,7 +596,6 @@ static int run_argv(int *argcp, const char ***argv)
                 */
                if (done_alias)
                        break;
-               save_env();
                if (!handle_alias(argcp, argv))
                        break;
                done_alias = 1;
index 7a5b23acf2155fb4e39dcb2f20944362cfbe0ac7..05d7910b7cdbd6fea7c835491caa774a46e4b7f8 100755 (executable)
@@ -7576,7 +7576,7 @@ sub git_object {
                        git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
                        or die_error(404, "Object does not exist");
                $type = <$fd>;
-               chomp $type;
+               defined $type && chomp $type;
                close $fd
                        or die_error(404, "Object does not exist");
 
diff --git a/http.c b/http.c
index 0da9e6639832a493f932e3ba332683d3d4ae73ae..dfc53c1e2554e76126459d6cb1f098facac28593 100644 (file)
--- a/http.c
+++ b/http.c
@@ -62,6 +62,26 @@ static long curl_low_speed_limit = -1;
 static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
+static const char *http_proxy_authmethod;
+static struct {
+       const char *name;
+       long curlauth_param;
+} proxy_authmethods[] = {
+       { "basic", CURLAUTH_BASIC },
+       { "digest", CURLAUTH_DIGEST },
+       { "negotiate", CURLAUTH_GSSNEGOTIATE },
+       { "ntlm", CURLAUTH_NTLM },
+#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
+       { "anyauth", CURLAUTH_ANY },
+#endif
+       /*
+        * CURLAUTH_DIGEST_IE has no corresponding command-line option in
+        * curl(1) and is not included in CURLAUTH_ANY, so we leave it out
+        * here, too
+        */
+};
+static struct credential proxy_auth = CREDENTIAL_INIT;
+static const char *curl_proxyuserpwd;
 static const char *curl_cookie_file;
 static int curl_save_cookies;
 struct credential http_auth = CREDENTIAL_INIT;
@@ -159,6 +179,9 @@ static void finish_active_slot(struct active_request_slot *slot)
 #else
                slot->results->auth_avail = 0;
 #endif
+
+               curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CONNECTCODE,
+                       &slot->results->http_connectcode);
        }
 
        /* Run callback if appropriate */
@@ -256,6 +279,9 @@ static int http_options(const char *var, const char *value, void *cb)
        if (!strcmp("http.proxy", var))
                return git_config_string(&curl_http_proxy, var, value);
 
+       if (!strcmp("http.proxyauthmethod", var))
+               return git_config_string(&http_proxy_authmethod, var, value);
+
        if (!strcmp("http.cookiefile", var))
                return git_config_string(&curl_cookie_file, var, value);
        if (!strcmp("http.savecookies", var)) {
@@ -304,6 +330,64 @@ static void init_curl_http_auth(CURL *result)
 #endif
 }
 
+/* *var must be free-able */
+static void var_override(const char **var, char *value)
+{
+       if (value) {
+               free((void *)*var);
+               *var = xstrdup(value);
+       }
+}
+
+static void set_proxyauth_name_password(CURL *result)
+{
+#if LIBCURL_VERSION_NUM >= 0x071301
+               curl_easy_setopt(result, CURLOPT_PROXYUSERNAME,
+                       proxy_auth.username);
+               curl_easy_setopt(result, CURLOPT_PROXYPASSWORD,
+                       proxy_auth.password);
+#else
+               struct strbuf s = STRBUF_INIT;
+
+               strbuf_addstr_urlencode(&s, proxy_auth.username, 1);
+               strbuf_addch(&s, ':');
+               strbuf_addstr_urlencode(&s, proxy_auth.password, 1);
+               curl_proxyuserpwd = strbuf_detach(&s, NULL);
+               curl_easy_setopt(result, CURLOPT_PROXYUSERPWD, curl_proxyuserpwd);
+#endif
+}
+
+static void init_curl_proxy_auth(CURL *result)
+{
+       if (proxy_auth.username) {
+               if (!proxy_auth.password)
+                       credential_fill(&proxy_auth);
+               set_proxyauth_name_password(result);
+       }
+
+       var_override(&http_proxy_authmethod, getenv("GIT_HTTP_PROXY_AUTHMETHOD"));
+
+#if LIBCURL_VERSION_NUM >= 0x070a07 /* CURLOPT_PROXYAUTH and CURLAUTH_ANY */
+       if (http_proxy_authmethod) {
+               int i;
+               for (i = 0; i < ARRAY_SIZE(proxy_authmethods); i++) {
+                       if (!strcmp(http_proxy_authmethod, proxy_authmethods[i].name)) {
+                               curl_easy_setopt(result, CURLOPT_PROXYAUTH,
+                                               proxy_authmethods[i].curlauth_param);
+                               break;
+                       }
+               }
+               if (i == ARRAY_SIZE(proxy_authmethods)) {
+                       warning("unsupported proxy authentication method %s: using anyauth",
+                                       http_proxy_authmethod);
+                       curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+               }
+       }
+       else
+               curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+#endif
+}
+
 static int has_cert_password(void)
 {
        if (ssl_cert == NULL || ssl_cert_password_required != 1)
@@ -462,6 +546,31 @@ static CURL *get_curl_handle(void)
                curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 #endif
 
+       /*
+        * CURL also examines these variables as a fallback; but we need to query
+        * them here in order to decide whether to prompt for missing password (cf.
+        * init_curl_proxy_auth()).
+        *
+        * Unlike many other common environment variables, these are historically
+        * lowercase only. It appears that CURL did not know this and implemented
+        * only uppercase variants, which was later corrected to take both - with
+        * the exception of http_proxy, which is lowercase only also in CURL. As
+        * the lowercase versions are the historical quasi-standard, they take
+        * precedence here, as in CURL.
+        */
+       if (!curl_http_proxy) {
+               if (!strcmp(http_auth.protocol, "https")) {
+                       var_override(&curl_http_proxy, getenv("HTTPS_PROXY"));
+                       var_override(&curl_http_proxy, getenv("https_proxy"));
+               } else {
+                       var_override(&curl_http_proxy, getenv("http_proxy"));
+               }
+               if (!curl_http_proxy) {
+                       var_override(&curl_http_proxy, getenv("ALL_PROXY"));
+                       var_override(&curl_http_proxy, getenv("all_proxy"));
+               }
+       }
+
        if (curl_http_proxy) {
                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
 #if LIBCURL_VERSION_NUM >= 0x071800
@@ -475,10 +584,18 @@ static CURL *get_curl_handle(void)
                        curl_easy_setopt(result,
                                CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
 #endif
+               if (strstr(curl_http_proxy, "://"))
+                       credential_from_url(&proxy_auth, curl_http_proxy);
+               else {
+                       struct strbuf url = STRBUF_INIT;
+                       strbuf_addf(&url, "http://%s", curl_http_proxy);
+                       credential_from_url(&proxy_auth, url.buf);
+                       strbuf_release(&url);
+               }
+
+               curl_easy_setopt(result, CURLOPT_PROXY, proxy_auth.host);
        }
-#if LIBCURL_VERSION_NUM >= 0x070a07
-       curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
-#endif
+       init_curl_proxy_auth(result);
 
        set_curl_keepalive(result);
 
@@ -519,6 +636,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
        if (remote && remote->http_proxy)
                curl_http_proxy = xstrdup(remote->http_proxy);
 
+       if (remote)
+               var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
+
        pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
        no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
 
@@ -617,6 +737,18 @@ void http_cleanup(void)
                curl_http_proxy = NULL;
        }
 
+       if (proxy_auth.password) {
+               memset(proxy_auth.password, 0, strlen(proxy_auth.password));
+               free(proxy_auth.password);
+               proxy_auth.password = NULL;
+       }
+
+       free((void *)curl_proxyuserpwd);
+       curl_proxyuserpwd = NULL;
+
+       free((void *)http_proxy_authmethod);
+       http_proxy_authmethod = NULL;
+
        if (cert_auth.password != NULL) {
                memset(cert_auth.password, 0, strlen(cert_auth.password));
                free(cert_auth.password);
@@ -946,6 +1078,8 @@ static int handle_curl_result(struct slot_results *results)
 
        if (results->curl_result == CURLE_OK) {
                credential_approve(&http_auth);
+               if (proxy_auth.password)
+                       credential_approve(&proxy_auth);
                return HTTP_OK;
        } else if (missing_target(results))
                return HTTP_MISSING_TARGET;
@@ -960,6 +1094,8 @@ static int handle_curl_result(struct slot_results *results)
                        return HTTP_REAUTH;
                }
        } else {
+               if (results->http_connectcode == 407)
+                       credential_reject(&proxy_auth);
 #if LIBCURL_VERSION_NUM >= 0x070c00
                if (!curl_errorstr[0])
                        strlcpy(curl_errorstr,
diff --git a/http.h b/http.h
index 4f97b60b5c8abdf5ab0610382a6d6fa289df2605..f83cfa686823728587b2a803c3e84a8cd4669220 100644 (file)
--- a/http.h
+++ b/http.h
@@ -54,6 +54,7 @@ struct slot_results {
        CURLcode curl_result;
        long http_code;
        long auth_avail;
+       long http_connectcode;
 };
 
 struct active_request_slot {
diff --git a/ident.c b/ident.c
index daf7e1ea8370e5b6a60c5a33a1591ef939655664..3da555634290f1812702e2d6da15e5a6806fe635 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -76,7 +76,7 @@ static int add_mailname_host(struct strbuf *buf)
                                strerror(errno));
                return -1;
        }
-       if (strbuf_getline(&mailnamebuf, mailname, '\n') == EOF) {
+       if (strbuf_getline(&mailnamebuf, mailname) == EOF) {
                if (ferror(mailname))
                        warning("cannot read /etc/mailname: %s",
                                strerror(errno));
index f289941f7e516be2f6265326188b3d8da70ef3aa..9f19ca10805a5f54a49b3a8fa2093f583bcea8c3 100644 (file)
@@ -732,7 +732,7 @@ static int read_one_header_line(struct strbuf *line, FILE *in)
        struct strbuf continuation = STRBUF_INIT;
 
        /* Get the first part of the line. */
-       if (strbuf_getline(line, in, '\n'))
+       if (strbuf_getline_lf(line, in))
                return 0;
 
        /*
@@ -756,7 +756,7 @@ static int read_one_header_line(struct strbuf *line, FILE *in)
                peek = fgetc(in); ungetc(peek, in);
                if (peek != ' ' && peek != '\t')
                        break;
-               if (strbuf_getline(&continuation, in, '\n'))
+               if (strbuf_getline_lf(&continuation, in))
                        break;
                continuation.buf[0] = ' ';
                strbuf_rtrim(&continuation);
@@ -769,7 +769,7 @@ static int read_one_header_line(struct strbuf *line, FILE *in)
 
 static int find_boundary(struct mailinfo *mi, struct strbuf *line)
 {
-       while (!strbuf_getline(line, mi->input, '\n')) {
+       while (!strbuf_getline_lf(line, mi->input)) {
                if (*(mi->content_top) && is_multipart_boundary(mi, line))
                        return 1;
        }
@@ -820,7 +820,7 @@ static int handle_boundary(struct mailinfo *mi, struct strbuf *line)
 
        strbuf_release(&newline);
        /* replenish line */
-       if (strbuf_getline(line, mi->input, '\n'))
+       if (strbuf_getline_lf(line, mi->input))
                return 0;
        strbuf_addch(line, '\n');
        return 1;
index c4e9bb7f6c0bde97c7c6d34094baa5ef7e318157..5dfc5cbd08e496748880bda6a67264c7d63f68b4 100644 (file)
@@ -32,14 +32,14 @@ void notes_cache_init(struct notes_cache *c, const char *name,
                     const char *validity)
 {
        struct strbuf ref = STRBUF_INIT;
-       int flags = 0;
+       int flags = NOTES_INIT_WRITABLE;
 
        memset(c, 0, sizeof(*c));
        c->validity = xstrdup(validity);
 
        strbuf_addf(&ref, "refs/notes/%s", name);
        if (!notes_cache_match_validity(ref.buf, validity))
-               flags = NOTES_INIT_EMPTY;
+               flags |= NOTES_INIT_EMPTY;
        init_notes(&c->tree, ref.buf, combine_notes_overwrite, flags);
        strbuf_release(&ref);
 }
@@ -49,7 +49,8 @@ int notes_cache_write(struct notes_cache *c)
        unsigned char tree_sha1[20];
        unsigned char commit_sha1[20];
 
-       if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref)
+       if (!c || !c->tree.initialized || !c->tree.update_ref ||
+           !*c->tree.update_ref)
                return -1;
        if (!c->tree.dirty)
                return 0;
@@ -59,8 +60,8 @@ int notes_cache_write(struct notes_cache *c)
        if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL,
                        commit_sha1, NULL, NULL) < 0)
                return -1;
-       if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
-                      0, UPDATE_REFS_QUIET_ON_ERR) < 0)
+       if (update_ref("update notes cache", c->tree.update_ref, commit_sha1,
+                      NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0)
                return -1;
 
        return 0;
index 299e34bccc5893529cb5db1abe061529304e6074..24a33616a47737e6ae8cf917080cbb314dcf2762 100644 (file)
@@ -37,7 +37,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
 
        if (!t)
                t = &default_notes_tree;
-       if (!t->initialized || !t->ref || !*t->ref)
+       if (!t->initialized || !t->update_ref || !*t->update_ref)
                die(_("Cannot commit uninitialized/unreferenced notes tree"));
        if (!t->dirty)
                return; /* don't have to commit an unchanged tree */
@@ -48,7 +48,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
 
        create_notes_commit(t, NULL, buf.buf, buf.len, commit_sha1);
        strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
-       update_ref(buf.buf, t->ref, commit_sha1, NULL, 0,
+       update_ref(buf.buf, t->update_ref, commit_sha1, NULL, 0,
                   UPDATE_REFS_DIE_ON_ERR);
 
        strbuf_release(&buf);
@@ -148,7 +148,7 @@ struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
                free(c);
                return NULL;
        }
-       c->trees = load_notes_trees(c->refs);
+       c->trees = load_notes_trees(c->refs, NOTES_INIT_WRITABLE);
        string_list_clear(c->refs, 0);
        free(c->refs);
        return c;
diff --git a/notes.c b/notes.c
index db77922130b4f7df6ab72122206a76d6c580faac..c1e503559076398b1edc5fabbaab8f3cac5ac7d6 100644 (file)
--- a/notes.c
+++ b/notes.c
@@ -1011,13 +1011,16 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
        t->first_non_note = NULL;
        t->prev_non_note = NULL;
        t->ref = xstrdup_or_null(notes_ref);
+       t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL;
        t->combine_notes = combine_notes;
        t->initialized = 1;
        t->dirty = 0;
 
        if (flags & NOTES_INIT_EMPTY || !notes_ref ||
-           read_ref(notes_ref, object_sha1))
+           get_sha1_treeish(notes_ref, object_sha1))
                return;
+       if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_sha1))
+               die("Cannot use notes ref %s", notes_ref);
        if (get_tree_entry(object_sha1, "", sha1, &mode))
                die("Failed to read notes tree referenced by %s (%s)",
                    notes_ref, sha1_to_hex(object_sha1));
@@ -1027,7 +1030,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
        load_subtree(t, &root_tree, t->root, 0);
 }
 
-struct notes_tree **load_notes_trees(struct string_list *refs)
+struct notes_tree **load_notes_trees(struct string_list *refs, int flags)
 {
        struct string_list_item *item;
        int counter = 0;
@@ -1035,7 +1038,7 @@ struct notes_tree **load_notes_trees(struct string_list *refs)
        trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *));
        for_each_string_list_item(item, refs) {
                struct notes_tree *t = xcalloc(1, sizeof(struct notes_tree));
-               init_notes(t, item->string, combine_notes_ignore, 0);
+               init_notes(t, item->string, combine_notes_ignore, flags);
                trees[counter++] = t;
        }
        trees[counter] = NULL;
@@ -1071,7 +1074,7 @@ void init_display_notes(struct display_notes_opt *opt)
                                                     item->string);
        }
 
-       display_notes_trees = load_notes_trees(&display_notes_refs);
+       display_notes_trees = load_notes_trees(&display_notes_refs, 0);
        string_list_clear(&display_notes_refs, 0);
 }
 
@@ -1303,3 +1306,13 @@ void expand_notes_ref(struct strbuf *sb)
        else
                strbuf_insert(sb, 0, "refs/notes/", 11);
 }
+
+void expand_loose_notes_ref(struct strbuf *sb)
+{
+       unsigned char object[20];
+
+       if (get_sha1(sb->buf, object)) {
+               /* fallback to expand_notes_ref */
+               expand_notes_ref(sb);
+       }
+}
diff --git a/notes.h b/notes.h
index 2a3f92338076ef8e4b8238aaf570c3273b0f28f0..5345642cfd1c36f3935cb4a7e38ab32f6992b383 100644 (file)
--- a/notes.h
+++ b/notes.h
@@ -44,6 +44,7 @@ extern struct notes_tree {
        struct int_node *root;
        struct non_note *first_non_note, *prev_non_note;
        char *ref;
+       char *update_ref;
        combine_notes_fn combine_notes;
        int initialized;
        int dirty;
@@ -71,6 +72,13 @@ const char *default_notes_ref(void);
  */
 #define NOTES_INIT_EMPTY 1
 
+/*
+ * By default, the notes tree is only readable, and the notes ref can be
+ * any treeish. The notes tree can however be made writable with this flag,
+ * in which case only strict ref names can be used.
+ */
+#define NOTES_INIT_WRITABLE 2
+
 /*
  * Initialize the given notes_tree with the notes tree structure at the given
  * ref. If given ref is NULL, the value of the $GIT_NOTES_REF environment
@@ -276,7 +284,7 @@ void format_display_notes(const unsigned char *object_sha1,
  * Load the notes tree from each ref listed in 'refs'.  The output is
  * an array of notes_tree*, terminated by a NULL.
  */
-struct notes_tree **load_notes_trees(struct string_list *refs);
+struct notes_tree **load_notes_trees(struct string_list *refs, int flags);
 
 /*
  * Add all refs that match 'glob' to the 'list'.
@@ -294,4 +302,11 @@ void string_list_add_refs_from_colon_sep(struct string_list *list,
 /* Expand inplace a note ref like "foo" or "notes/foo" into "refs/notes/foo" */
 void expand_notes_ref(struct strbuf *sb);
 
+/*
+ * Similar to expand_notes_ref, but will check whether the ref can be located
+ * via get_sha1 first, and only falls back to expand_notes_ref in the case
+ * where get_sha1 fails.
+ */
+void expand_loose_notes_ref(struct strbuf *sb);
+
 #endif
index cb9c62280389cfdb3bcaf483ac4edf2f0a00969f..dd8dc16e676fb3e928560002c0cb7e1f36910e1a 100644 (file)
@@ -33,9 +33,6 @@ static struct bitmap_index {
        /* Packfile to which this bitmap index belongs to */
        struct packed_git *pack;
 
-       /* reverse index for the packfile */
-       struct pack_revindex *reverse_index;
-
        /*
         * Mark the first `reuse_objects` in the packfile as reused:
         * they will be sent as-is without using them for repacking
@@ -308,7 +305,7 @@ static int load_pack_bitmap(void)
 
        bitmap_git.bitmaps = kh_init_sha1();
        bitmap_git.ext_index.positions = kh_init_sha1_pos();
-       bitmap_git.reverse_index = revindex_for_pack(bitmap_git.pack);
+       load_pack_revindex(bitmap_git.pack);
 
        if (!(bitmap_git.commits = read_bitmap_1(&bitmap_git)) ||
                !(bitmap_git.trees = read_bitmap_1(&bitmap_git)) ||
@@ -380,7 +377,7 @@ static inline int bitmap_position_packfile(const unsigned char *sha1)
        if (!offset)
                return -1;
 
-       return find_revindex_position(bitmap_git.reverse_index, offset);
+       return find_revindex_position(bitmap_git.pack, offset);
 }
 
 static int bitmap_position(const unsigned char *sha1)
@@ -630,7 +627,7 @@ static void show_objects_for_type(
                        if (pos + offset < bitmap_git.reuse_objects)
                                continue;
 
-                       entry = &bitmap_git.reverse_index->revindex[pos + offset];
+                       entry = &bitmap_git.pack->revindex[pos + offset];
                        sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
 
                        if (bitmap_git.hashes)
@@ -804,7 +801,7 @@ int reuse_partial_packfile_from_bitmap(struct packed_git **packfile,
                return -1;
 
        bitmap_git.reuse_objects = *entries = reuse_objects;
-       *up_to = bitmap_git.reverse_index->revindex[reuse_objects].offset;
+       *up_to = bitmap_git.pack->revindex[reuse_objects].offset;
        *packfile = bitmap_git.pack;
 
        return 0;
@@ -1038,7 +1035,7 @@ int rebuild_existing_bitmaps(struct packing_data *mapping,
                struct revindex_entry *entry;
                struct object_entry *oe;
 
-               entry = &bitmap_git.reverse_index->revindex[i];
+               entry = &bitmap_git.pack->revindex[i];
                sha1 = nth_packed_object_sha1(bitmap_git.pack, entry->nr);
                oe = packlist_find(mapping, sha1, NULL);
 
index e542ea7703a740916f8d2cac9176674782d37f61..155a8a3d69bf7d1c4c72aaa36ad483dae33ca9b5 100644 (file)
@@ -8,52 +8,13 @@
  * size is easily available by examining the pack entry header).  It is
  * also rather expensive to find the sha1 for an object given its offset.
  *
- * We build a hashtable of existing packs (pack_revindex), and keep reverse
- * index here -- pack index file is sorted by object name mapping to offset;
- * this pack_revindex[].revindex array is a list of offset/index_nr pairs
+ * The pack index file is sorted by object name mapping to offset;
+ * this revindex array is a list of offset/index_nr pairs
  * ordered by offset, so if you know the offset of an object, next offset
  * is where its packed representation ends and the index_nr can be used to
  * get the object sha1 from the main index.
  */
 
-static struct pack_revindex *pack_revindex;
-static int pack_revindex_hashsz;
-
-static int pack_revindex_ix(struct packed_git *p)
-{
-       unsigned long ui = (unsigned long)(intptr_t)p;
-       int i;
-
-       ui = ui ^ (ui >> 16); /* defeat structure alignment */
-       i = (int)(ui % pack_revindex_hashsz);
-       while (pack_revindex[i].p) {
-               if (pack_revindex[i].p == p)
-                       return i;
-               if (++i == pack_revindex_hashsz)
-                       i = 0;
-       }
-       return -1 - i;
-}
-
-static void init_pack_revindex(void)
-{
-       int num;
-       struct packed_git *p;
-
-       for (num = 0, p = packed_git; p; p = p->next)
-               num++;
-       if (!num)
-               return;
-       pack_revindex_hashsz = num * 11;
-       pack_revindex = xcalloc(pack_revindex_hashsz, sizeof(*pack_revindex));
-       for (p = packed_git; p; p = p->next) {
-               num = pack_revindex_ix(p);
-               num = - 1 - num;
-               pack_revindex[num].p = p;
-       }
-       /* revindex elements are lazily initialized */
-}
-
 /*
  * This is a least-significant-digit radix sort.
  *
@@ -154,14 +115,13 @@ static void sort_revindex(struct revindex_entry *entries, unsigned n, off_t max)
 /*
  * Ordered list of offsets of objects in the pack.
  */
-static void create_pack_revindex(struct pack_revindex *rix)
+static void create_pack_revindex(struct packed_git *p)
 {
-       struct packed_git *p = rix->p;
        unsigned num_ent = p->num_objects;
        unsigned i;
        const char *index = p->index_data;
 
-       rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
+       p->revindex = xmalloc(sizeof(*p->revindex) * (num_ent + 1));
        index += 4 * 256;
 
        if (p->index_version > 1) {
@@ -171,55 +131,42 @@ static void create_pack_revindex(struct pack_revindex *rix)
                for (i = 0; i < num_ent; i++) {
                        uint32_t off = ntohl(*off_32++);
                        if (!(off & 0x80000000)) {
-                               rix->revindex[i].offset = off;
+                               p->revindex[i].offset = off;
                        } else {
-                               rix->revindex[i].offset =
+                               p->revindex[i].offset =
                                        ((uint64_t)ntohl(*off_64++)) << 32;
-                               rix->revindex[i].offset |=
+                               p->revindex[i].offset |=
                                        ntohl(*off_64++);
                        }
-                       rix->revindex[i].nr = i;
+                       p->revindex[i].nr = i;
                }
        } else {
                for (i = 0; i < num_ent; i++) {
                        uint32_t hl = *((uint32_t *)(index + 24 * i));
-                       rix->revindex[i].offset = ntohl(hl);
-                       rix->revindex[i].nr = i;
+                       p->revindex[i].offset = ntohl(hl);
+                       p->revindex[i].nr = i;
                }
        }
 
        /* This knows the pack format -- the 20-byte trailer
         * follows immediately after the last object data.
         */
-       rix->revindex[num_ent].offset = p->pack_size - 20;
-       rix->revindex[num_ent].nr = -1;
-       sort_revindex(rix->revindex, num_ent, p->pack_size);
+       p->revindex[num_ent].offset = p->pack_size - 20;
+       p->revindex[num_ent].nr = -1;
+       sort_revindex(p->revindex, num_ent, p->pack_size);
 }
 
-struct pack_revindex *revindex_for_pack(struct packed_git *p)
+void load_pack_revindex(struct packed_git *p)
 {
-       int num;
-       struct pack_revindex *rix;
-
-       if (!pack_revindex_hashsz)
-               init_pack_revindex();
-
-       num = pack_revindex_ix(p);
-       if (num < 0)
-               die("internal error: pack revindex fubar");
-
-       rix = &pack_revindex[num];
-       if (!rix->revindex)
-               create_pack_revindex(rix);
-
-       return rix;
+       if (!p->revindex)
+               create_pack_revindex(p);
 }
 
-int find_revindex_position(struct pack_revindex *pridx, off_t ofs)
+int find_revindex_position(struct packed_git *p, off_t ofs)
 {
        int lo = 0;
-       int hi = pridx->p->num_objects + 1;
-       struct revindex_entry *revindex = pridx->revindex;
+       int hi = p->num_objects + 1;
+       struct revindex_entry *revindex = p->revindex;
 
        do {
                unsigned mi = lo + (hi - lo) / 2;
@@ -237,11 +184,13 @@ int find_revindex_position(struct pack_revindex *pridx, off_t ofs)
 
 struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
 {
-       struct pack_revindex *pridx = revindex_for_pack(p);
-       int pos = find_revindex_position(pridx, ofs);
+       int pos;
+
+       load_pack_revindex(p);
+       pos = find_revindex_position(p, ofs);
 
        if (pos < 0)
                return NULL;
 
-       return pridx->revindex + pos;
+       return p->revindex + pos;
 }
index d737f989659da7f58d7df153de9a2ac30b162108..e262f3efe84962e774c1784129de4c17de3936c8 100644 (file)
@@ -1,18 +1,15 @@
 #ifndef PACK_REVINDEX_H
 #define PACK_REVINDEX_H
 
+struct packed_git;
+
 struct revindex_entry {
        off_t offset;
        unsigned int nr;
 };
 
-struct pack_revindex {
-       struct packed_git *p;
-       struct revindex_entry *revindex;
-};
-
-struct pack_revindex *revindex_for_pack(struct packed_git *p);
-int find_revindex_position(struct pack_revindex *pridx, off_t ofs);
+void load_pack_revindex(struct packed_git *p);
+int find_revindex_position(struct packed_git *p, off_t ofs);
 
 struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs);
 
diff --git a/path.c b/path.c
index 3cd155e27dddee6774d48522945c0615f6207d8c..8b7e16812927645367c4912e88d2a5f3065efb85 100644 (file)
--- a/path.c
+++ b/path.c
@@ -782,13 +782,10 @@ const char *relative_path(const char *in, const char *prefix,
        else if (!prefix_len)
                return in;
 
-       if (have_same_root(in, prefix)) {
+       if (have_same_root(in, prefix))
                /* bypass dos_drive, for "c:" is identical to "C:" */
-               if (has_dos_drive_prefix(in)) {
-                       i = 2;
-                       j = 2;
-               }
-       } else {
+               i = j = has_dos_drive_prefix(in);
+       else {
                return in;
        }
 
@@ -943,11 +940,10 @@ const char *remove_leading_path(const char *in, const char *prefix)
 int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
 {
        char *dst0;
+       int i;
 
-       if (has_dos_drive_prefix(src)) {
+       for (i = has_dos_drive_prefix(src); i > 0; i--)
                *dst++ = *src++;
-               *dst++ = *src++;
-       }
        dst0 = dst;
 
        if (is_dir_sep(*src)) {
index 4a499fcb38daf4ab8d3e20ca0fa10e5732e684a9..e7646968011234c09e1565577357a7678c015762 100644 (file)
@@ -81,7 +81,6 @@ sub prepare_config_once {
        SVN::_Core::svn_config_ensure($config_dir, undef);
        my ($baton, $callbacks) = SVN::Core::auth_open_helper(_auth_providers);
        my $config = SVN::Core::config_get_config($config_dir);
-       my $dont_store_passwords = 1;
        my $conf_t = $config->{'config'};
 
        no warnings 'once';
@@ -93,9 +92,14 @@ sub prepare_config_once {
            $SVN::_Core::SVN_CONFIG_SECTION_AUTH,
            $SVN::_Core::SVN_CONFIG_OPTION_STORE_PASSWORDS,
            1) == 0) {
+               my $val = '1';
+               if (::compare_svn_version('1.9.0') < 0) { # pre-SVN r1553823
+                       my $dont_store_passwords = 1;
+                       $val = bless \$dont_store_passwords, "_p_void";
+               }
                SVN::_Core::svn_auth_set_parameter($baton,
                    $SVN::_Core::SVN_AUTH_PARAM_DONT_STORE_PASSWORDS,
-                   bless (\$dont_store_passwords, "_p_void"));
+                   $val);
        }
        if (SVN::_Core::svn_config_get_bool($conf_t,
            $SVN::_Core::SVN_CONFIG_SECTION_AUTH,
index 84616c8e219bf3cf902643a8da62a2060d335c36..d9fb78bc559ac9de642833df5af63e33481cad52 100644 (file)
@@ -327,7 +327,7 @@ int ie_match_stat(const struct index_state *istate,
         * by definition never matches what is in the work tree until it
         * actually gets added.
         */
-       if (ce->ce_flags & CE_INTENT_TO_ADD)
+       if (ce_intent_to_add(ce))
                return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED;
 
        changed = ce_match_stat_basic(ce, st);
@@ -1237,7 +1237,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
 
                        if (cache_errno == ENOENT)
                                fmt = deleted_fmt;
-                       else if (ce->ce_flags & CE_INTENT_TO_ADD)
+                       else if (ce_intent_to_add(ce))
                                fmt = added_fmt; /* must be before other checks */
                        else if (changed & TYPE_CHANGED)
                                fmt = typechange_fmt;
@@ -1519,6 +1519,28 @@ static void check_ce_order(struct index_state *istate)
        }
 }
 
+static void tweak_untracked_cache(struct index_state *istate)
+{
+       switch (git_config_get_untracked_cache()) {
+       case -1: /* keep: do nothing */
+               break;
+       case 0: /* false */
+               remove_untracked_cache(istate);
+               break;
+       case 1: /* true */
+               add_untracked_cache(istate);
+               break;
+       default: /* unknown value: do nothing */
+               break;
+       }
+}
+
+static void post_read_index_from(struct index_state *istate)
+{
+       check_ce_order(istate);
+       tweak_untracked_cache(istate);
+}
+
 /* remember to discard_cache() before reading a different cache! */
 int do_read_index(struct index_state *istate, const char *path, int must_exist)
 {
@@ -1622,9 +1644,10 @@ int read_index_from(struct index_state *istate, const char *path)
                return istate->cache_nr;
 
        ret = do_read_index(istate, path, 0);
+
        split_index = istate->split_index;
        if (!split_index || is_null_sha1(split_index->base_sha1)) {
-               check_ce_order(istate);
+               post_read_index_from(istate);
                return ret;
        }
 
@@ -1642,7 +1665,7 @@ int read_index_from(struct index_state *istate, const char *path)
                             sha1_to_hex(split_index->base_sha1)),
                    sha1_to_hex(split_index->base->sha1));
        merge_base_index(istate);
-       check_ce_order(istate);
+       post_read_index_from(istate);
        return ret;
 }
 
index 7bef7f8dac644b49a2cb13d8d5154fd563d6e8a0..f097176ed93229fe75533e21dc60e0bbc5a4e7ef 100644 (file)
@@ -763,6 +763,29 @@ static inline char *copy_advance(char *dst, const char *src)
        return dst;
 }
 
+static const char *strip_ref_components(const char *refname, const char *nr_arg)
+{
+       char *end;
+       long nr = strtol(nr_arg, &end, 10);
+       long remaining = nr;
+       const char *start = refname;
+
+       if (nr < 1 || *end != '\0')
+               die(":strip= requires a positive integer argument");
+
+       while (remaining) {
+               switch (*start++) {
+               case '\0':
+                       die("ref '%s' does not have %ld components to :strip",
+                           refname, nr);
+               case '/':
+                       remaining--;
+                       break;
+               }
+       }
+       return start;
+}
+
 /*
  * Parse the object referred by ref, and grab needed value.
  */
@@ -909,11 +932,14 @@ static void populate_value(struct ref_array_item *ref)
                formatp = strchr(name, ':');
                if (formatp) {
                        int num_ours, num_theirs;
+                       const char *arg;
 
                        formatp++;
                        if (!strcmp(formatp, "short"))
                                refname = shorten_unambiguous_ref(refname,
                                                      warn_ambiguous_refs);
+                       else if (skip_prefix(formatp, "strip=", &arg))
+                               refname = strip_ref_components(refname, arg);
                        else if (!strcmp(formatp, "track") &&
                                 (starts_with(name, "upstream") ||
                                  starts_with(name, "push"))) {
index 85b8a54241048bb2cc037c2c114b49e7c7e7968b..0ebd1da5ceb835066cf4eccd81eda4fba2cc0ac2 100644 (file)
@@ -221,6 +221,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
        struct commit_info *commit_info =
                get_commit_info(commit, &info->reflogs, 0);
        struct commit_reflog *commit_reflog;
+       struct object *logobj;
        struct reflog_info *reflog;
 
        info->last_commit_reflog = NULL;
@@ -232,15 +233,20 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
                commit->parents = NULL;
                return;
        }
-
-       reflog = &commit_reflog->reflogs->items[commit_reflog->recno];
        info->last_commit_reflog = commit_reflog;
-       commit_reflog->recno--;
-       commit_info->commit = (struct commit *)parse_object(reflog->osha1);
-       if (!commit_info->commit) {
+
+       do {
+               reflog = &commit_reflog->reflogs->items[commit_reflog->recno];
+               commit_reflog->recno--;
+               logobj = parse_object(reflog->osha1);
+       } while (commit_reflog->recno && (logobj && logobj->type != OBJ_COMMIT));
+
+       if (!logobj || logobj->type != OBJ_COMMIT) {
+               commit_info->commit = NULL;
                commit->parents = NULL;
                return;
        }
+       commit_info->commit = (struct commit *)logobj;
 
        commit->parents = xcalloc(1, sizeof(struct commit_list));
        commit->parents->item = commit_info->commit;
diff --git a/refs.h b/refs.h
index 7a040774890637253847e82e3ea3a90ac081f757..3c3da29bf0064cd189a6b0c8dc1a7daeb953150e 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -292,7 +292,7 @@ extern char *shorten_unambiguous_ref(const char *refname, int strict);
 /** rename ref, return 0 on success **/
 extern int rename_ref(const char *oldref, const char *newref, const char *logmsg);
 
-extern int create_symref(const char *ref, const char *refs_heads_master, const char *logmsg);
+extern int create_symref(const char *refname, const char *target, const char *logmsg);
 
 enum action_on_err {
        UPDATE_REFS_MSG_ON_ERR,
index c648b5e853c347f0978d835cb057a9a2831bf0dd..b56976288819c87307c03e4e5abf9b9458d09970 100644 (file)
@@ -933,6 +933,10 @@ static void clear_loose_ref_cache(struct ref_cache *refs)
        }
 }
 
+/*
+ * Create a new submodule ref cache and add it to the internal
+ * set of caches.
+ */
 static struct ref_cache *create_ref_cache(const char *submodule)
 {
        int len;
@@ -942,16 +946,12 @@ static struct ref_cache *create_ref_cache(const char *submodule)
        len = strlen(submodule) + 1;
        refs = xcalloc(1, sizeof(struct ref_cache) + len);
        memcpy(refs->name, submodule, len);
+       refs->next = submodule_ref_caches;
+       submodule_ref_caches = refs;
        return refs;
 }
 
-/*
- * Return a pointer to a ref_cache for the specified submodule. For
- * the main repository, use submodule==NULL. The returned structure
- * will be allocated and initialized but not necessarily populated; it
- * should not be freed.
- */
-static struct ref_cache *get_ref_cache(const char *submodule)
+static struct ref_cache *lookup_ref_cache(const char *submodule)
 {
        struct ref_cache *refs;
 
@@ -961,10 +961,20 @@ static struct ref_cache *get_ref_cache(const char *submodule)
        for (refs = submodule_ref_caches; refs; refs = refs->next)
                if (!strcmp(submodule, refs->name))
                        return refs;
+       return NULL;
+}
 
-       refs = create_ref_cache(submodule);
-       refs->next = submodule_ref_caches;
-       submodule_ref_caches = refs;
+/*
+ * Return a pointer to a ref_cache for the specified submodule. For
+ * the main repository, use submodule==NULL. The returned structure
+ * will be allocated and initialized but not necessarily populated; it
+ * should not be freed.
+ */
+static struct ref_cache *get_ref_cache(const char *submodule)
+{
+       struct ref_cache *refs = lookup_ref_cache(submodule);
+       if (!refs)
+               refs = create_ref_cache(submodule);
        return refs;
 }
 
@@ -1336,16 +1346,24 @@ static int resolve_gitlink_ref_recursive(struct ref_cache *refs,
 int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *sha1)
 {
        int len = strlen(path), retval;
-       char *submodule;
+       struct strbuf submodule = STRBUF_INIT;
        struct ref_cache *refs;
 
        while (len && path[len-1] == '/')
                len--;
        if (!len)
                return -1;
-       submodule = xstrndup(path, len);
-       refs = get_ref_cache(submodule);
-       free(submodule);
+
+       strbuf_add(&submodule, path, len);
+       refs = lookup_ref_cache(submodule.buf);
+       if (!refs) {
+               if (!is_nonbare_repository_dir(&submodule)) {
+                       strbuf_release(&submodule);
+                       return -1;
+               }
+               refs = create_ref_cache(submodule.buf);
+       }
+       strbuf_release(&submodule);
 
        retval = resolve_gitlink_ref_recursive(refs, refname, sha1, 0);
        return retval;
@@ -1840,12 +1858,17 @@ static int verify_lock(struct ref_lock *lock,
        if (read_ref_full(lock->ref_name,
                          mustexist ? RESOLVE_REF_READING : 0,
                          lock->old_oid.hash, NULL)) {
-               int save_errno = errno;
-               strbuf_addf(err, "can't verify ref %s", lock->ref_name);
-               errno = save_errno;
-               return -1;
+               if (old_sha1) {
+                       int save_errno = errno;
+                       strbuf_addf(err, "can't verify ref %s", lock->ref_name);
+                       errno = save_errno;
+                       return -1;
+               } else {
+                       hashclr(lock->old_oid.hash);
+                       return 0;
+               }
        }
-       if (hashcmp(lock->old_oid.hash, old_sha1)) {
+       if (old_sha1 && hashcmp(lock->old_oid.hash, old_sha1)) {
                strbuf_addf(err, "ref %s is at %s but expected %s",
                            lock->ref_name,
                            sha1_to_hex(lock->old_oid.hash),
@@ -1882,7 +1905,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
        const char *orig_refname = refname;
        struct ref_lock *lock;
        int last_errno = 0;
-       int type, lflags;
+       int type;
+       int lflags = 0;
        int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
        int resolve_flags = 0;
        int attempts_remaining = 3;
@@ -1893,10 +1917,11 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
 
        if (mustexist)
                resolve_flags |= RESOLVE_REF_READING;
-       if (flags & REF_DELETING) {
+       if (flags & REF_DELETING)
                resolve_flags |= RESOLVE_REF_ALLOW_BAD_NAME;
-               if (flags & REF_NODEREF)
-                       resolve_flags |= RESOLVE_REF_NO_RECURSE;
+       if (flags & REF_NODEREF) {
+               resolve_flags |= RESOLVE_REF_NO_RECURSE;
+               lflags |= LOCK_NO_DEREF;
        }
 
        refname = resolve_ref_unsafe(refname, resolve_flags,
@@ -1932,6 +1957,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
 
                goto error_return;
        }
+
+       if (flags & REF_NODEREF)
+               refname = orig_refname;
+
        /*
         * If the ref did not exist and we are creating it, make sure
         * there is no existing packed ref whose name begins with our
@@ -1947,11 +1976,6 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
 
        lock->lk = xcalloc(1, sizeof(struct lock_file));
 
-       lflags = 0;
-       if (flags & REF_NODEREF) {
-               refname = orig_refname;
-               lflags |= LOCK_NO_DEREF;
-       }
        lock->ref_name = xstrdup(refname);
        lock->orig_ref_name = xstrdup(orig_refname);
        strbuf_git_path(&ref_file, "%s", refname);
@@ -1985,7 +2009,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *refname,
                        goto error_return;
                }
        }
-       if (old_sha1 && verify_lock(lock, old_sha1, mustexist, err)) {
+       if (verify_lock(lock, old_sha1, mustexist, err)) {
                last_errno = errno;
                goto error_return;
        }
@@ -2811,73 +2835,72 @@ static int commit_ref_update(struct ref_lock *lock,
        return 0;
 }
 
-int create_symref(const char *ref_target, const char *refs_heads_master,
-                 const char *logmsg)
+static int create_ref_symlink(struct ref_lock *lock, const char *target)
 {
-       char *lockpath = NULL;
-       char ref[1000];
-       int fd, len, written;
-       char *git_HEAD = git_pathdup("%s", ref_target);
-       unsigned char old_sha1[20], new_sha1[20];
-       struct strbuf err = STRBUF_INIT;
-
-       if (logmsg && read_ref(ref_target, old_sha1))
-               hashclr(old_sha1);
-
-       if (safe_create_leading_directories(git_HEAD) < 0)
-               return error("unable to create directory for %s", git_HEAD);
-
+       int ret = -1;
 #ifndef NO_SYMLINK_HEAD
-       if (prefer_symlink_refs) {
-               unlink(git_HEAD);
-               if (!symlink(refs_heads_master, git_HEAD))
-                       goto done;
+       char *ref_path = get_locked_file_path(lock->lk);
+       unlink(ref_path);
+       ret = symlink(target, ref_path);
+       free(ref_path);
+
+       if (ret)
                fprintf(stderr, "no symlink - falling back to symbolic ref\n");
-       }
 #endif
+       return ret;
+}
 
-       len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
-       if (sizeof(ref) <= len) {
-               error("refname too long: %s", refs_heads_master);
-               goto error_free_return;
-       }
-       lockpath = mkpathdup("%s.lock", git_HEAD);
-       fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
-       if (fd < 0) {
-               error("Unable to open %s for writing", lockpath);
-               goto error_free_return;
-       }
-       written = write_in_full(fd, ref, len);
-       if (close(fd) != 0 || written != len) {
-               error("Unable to write to %s", lockpath);
-               goto error_unlink_return;
-       }
-       if (rename(lockpath, git_HEAD) < 0) {
-               error("Unable to create %s", git_HEAD);
-               goto error_unlink_return;
-       }
-       if (adjust_shared_perm(git_HEAD)) {
-               error("Unable to fix permissions on %s", lockpath);
-       error_unlink_return:
-               unlink_or_warn(lockpath);
-       error_free_return:
-               free(lockpath);
-               free(git_HEAD);
-               return -1;
+static void update_symref_reflog(struct ref_lock *lock, const char *refname,
+                                const char *target, const char *logmsg)
+{
+       struct strbuf err = STRBUF_INIT;
+       unsigned char new_sha1[20];
+       if (logmsg && !read_ref(target, new_sha1) &&
+           log_ref_write(refname, lock->old_oid.hash, new_sha1, logmsg, 0, &err)) {
+               error("%s", err.buf);
+               strbuf_release(&err);
        }
-       free(lockpath);
+}
 
-#ifndef NO_SYMLINK_HEAD
-       done:
-#endif
-       if (logmsg && !read_ref(refs_heads_master, new_sha1) &&
-               log_ref_write(ref_target, old_sha1, new_sha1, logmsg, 0, &err)) {
+static int create_symref_locked(struct ref_lock *lock, const char *refname,
+                               const char *target, const char *logmsg)
+{
+       if (prefer_symlink_refs && !create_ref_symlink(lock, target)) {
+               update_symref_reflog(lock, refname, target, logmsg);
+               return 0;
+       }
+
+       if (!fdopen_lock_file(lock->lk, "w"))
+               return error("unable to fdopen %s: %s",
+                            lock->lk->tempfile.filename.buf, strerror(errno));
+
+       update_symref_reflog(lock, refname, target, logmsg);
+
+       /* no error check; commit_ref will check ferror */
+       fprintf(lock->lk->tempfile.fp, "ref: %s\n", target);
+       if (commit_ref(lock) < 0)
+               return error("unable to write symref for %s: %s", refname,
+                            strerror(errno));
+       return 0;
+}
+
+int create_symref(const char *refname, const char *target, const char *logmsg)
+{
+       struct strbuf err = STRBUF_INIT;
+       struct ref_lock *lock;
+       int ret;
+
+       lock = lock_ref_sha1_basic(refname, NULL, NULL, NULL, REF_NODEREF, NULL,
+                                  &err);
+       if (!lock) {
                error("%s", err.buf);
                strbuf_release(&err);
+               return -1;
        }
 
-       free(git_HEAD);
-       return 0;
+       ret = create_symref_locked(lock, refname, target, logmsg);
+       unlock_ref(lock);
+       return ret;
 }
 
 int reflog_exists(const char *refname)
index f404faf0f4b9ec298ccbae34fae0c79283884d26..c7048575fbdca1bd8dc57c114d0cfdc031e63039 100644 (file)
@@ -827,7 +827,7 @@ static void parse_fetch(struct strbuf *buf)
                        die("http transport does not support %s", buf->buf);
 
                strbuf_reset(buf);
-               if (strbuf_getline(buf, stdin, '\n') == EOF)
+               if (strbuf_getline_lf(buf, stdin) == EOF)
                        return;
                if (!*buf->buf)
                        break;
@@ -940,7 +940,7 @@ static void parse_push(struct strbuf *buf)
                        die("http transport does not support %s", buf->buf);
 
                strbuf_reset(buf);
-               if (strbuf_getline(buf, stdin, '\n') == EOF)
+               if (strbuf_getline_lf(buf, stdin) == EOF)
                        goto free_specs;
                if (!*buf->buf)
                        break;
@@ -990,7 +990,7 @@ int main(int argc, const char **argv)
        do {
                const char *arg;
 
-               if (strbuf_getline(&buf, stdin, '\n') == EOF) {
+               if (strbuf_getline_lf(&buf, stdin) == EOF) {
                        if (ferror(stdin))
                                error("remote-curl: error reading command stream from git");
                        return 1;
index f599c372c64dd8930f9640e9503f73c5edaff49c..f05ff45298207258c257c2118206fbbfa0a4c670 100644 (file)
@@ -154,7 +154,7 @@ static void check_or_regenerate_marks(int latestrev)
                fclose(marksfile);
        } else {
                strbuf_addf(&sb, ":%d ", latestrev);
-               while (strbuf_getline(&line, marksfile, '\n') != EOF) {
+               while (strbuf_getline_lf(&line, marksfile) != EOF) {
                        if (starts_with(line.buf, sb.buf)) {
                                found++;
                                break;
@@ -322,7 +322,7 @@ int main(int argc, char **argv)
        marksfilename = marksfilename_sb.buf;
 
        while (1) {
-               if (strbuf_getline(&buf, stdin, '\n') == EOF) {
+               if (strbuf_getline_lf(&buf, stdin) == EOF) {
                        if (ferror(stdin))
                                die("Error reading command stream");
                        else
index 9d34b5a5dafa217e2ce9cb1b7e9a4ab74908f7af..35940a5602807542eeae12a45bb845e73a99339c 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -256,7 +256,7 @@ static void read_remotes_file(struct remote *remote)
        if (!f)
                return;
        remote->origin = REMOTE_REMOTES;
-       while (strbuf_getline(&buf, f, '\n') != EOF) {
+       while (strbuf_getline(&buf, f) != EOF) {
                const char *v;
 
                strbuf_rtrim(&buf);
@@ -281,7 +281,7 @@ static void read_branches_file(struct remote *remote)
        if (!f)
                return;
 
-       strbuf_getline(&buf, f, '\n');
+       strbuf_getline_lf(&buf, f);
        fclose(f);
        strbuf_trim(&buf);
        if (!buf.len) {
@@ -428,6 +428,9 @@ static int handle_config(const char *key, const char *value, void *cb)
        } else if (!strcmp(subkey, ".proxy")) {
                return git_config_string((const char **)&remote->http_proxy,
                                         key, value);
+       } else if (!strcmp(subkey, ".proxyauthmethod")) {
+               return git_config_string((const char **)&remote->http_proxy_authmethod,
+                                        key, value);
        } else if (!strcmp(subkey, ".vcs")) {
                return git_config_string(&remote->foreign_vcs, key, value);
        }
index 4a039bae0b15d6d28aace0c62287c3f3bb11befa..4fd7a0f9b2764d3de935f6387f6a93bfd7ab13b0 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -54,6 +54,7 @@ struct remote {
         * for curl remotes only
         */
        char *http_proxy;
+       char *http_proxy_authmethod;
 };
 
 struct remote *remote_get(const char *name);
index 0a282f533b3e225a996221d614de8bdc960092a3..f24ead53d537b05d7819ce53b45b05a15ec60a96 100644 (file)
@@ -1635,10 +1635,7 @@ static void append_prune_data(struct cmdline_pathspec *prune, const char **av)
 static void read_pathspec_from_stdin(struct rev_info *revs, struct strbuf *sb,
                                     struct cmdline_pathspec *prune)
 {
-       while (strbuf_getwholeline(sb, stdin, '\n') != EOF) {
-               int len = sb->len;
-               if (len && sb->buf[len - 1] == '\n')
-                       sb->buf[--len] = '\0';
+       while (strbuf_getline(sb, stdin) != EOF) {
                ALLOC_GROW(prune->path, prune->nr + 1, prune->alloc);
                prune->path[prune->nr++] = xstrdup(sb->buf);
        }
@@ -1655,10 +1652,8 @@ static void read_revisions_from_stdin(struct rev_info *revs,
        warn_on_object_refname_ambiguity = 0;
 
        strbuf_init(&sb, 1000);
-       while (strbuf_getwholeline(&sb, stdin, '\n') != EOF) {
+       while (strbuf_getline(&sb, stdin) != EOF) {
                int len = sb.len;
-               if (len && sb.buf[len - 1] == '\n')
-                       sb.buf[--len] = '\0';
                if (!len)
                        break;
                if (sb.buf[0] == '-') {
@@ -2049,7 +2044,7 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg
        } else if (!strcmp(arg, "--ignore-missing")) {
                revs->ignore_missing = 1;
        } else {
-               int opts = diff_opt_parse(&revs->diffopt, argv, argc);
+               int opts = diff_opt_parse(&revs->diffopt, argv, argc, revs->prefix);
                if (!opts)
                        unkv[(*unkc)++] = arg;
                return opts;
index 13fa452e8c3d5a5e20e24a969d53ce7ade4019bf..cdf01845790849f863aef4195a68e12fa19ca543 100644 (file)
@@ -3,6 +3,8 @@
 #include "exec_cmd.h"
 #include "sigchain.h"
 #include "argv-array.h"
+#include "thread-utils.h"
+#include "strbuf.h"
 
 void child_process_init(struct child_process *child)
 {
@@ -245,7 +247,7 @@ static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
                error("waitpid is confused (%s)", argv0);
        } else if (WIFSIGNALED(status)) {
                code = WTERMSIG(status);
-               if (code != SIGINT && code != SIGQUIT)
+               if (code != SIGINT && code != SIGQUIT && code != SIGPIPE)
                        error("%s died of signal %d", argv0, code);
                /*
                 * This return value is chosen so that code & 0xff
@@ -865,3 +867,336 @@ int capture_command(struct child_process *cmd, struct strbuf *buf, size_t hint)
        close(cmd->out);
        return finish_command(cmd);
 }
+
+enum child_state {
+       GIT_CP_FREE,
+       GIT_CP_WORKING,
+       GIT_CP_WAIT_CLEANUP,
+};
+
+struct parallel_processes {
+       void *data;
+
+       int max_processes;
+       int nr_processes;
+
+       get_next_task_fn get_next_task;
+       start_failure_fn start_failure;
+       task_finished_fn task_finished;
+
+       struct {
+               enum child_state state;
+               struct child_process process;
+               struct strbuf err;
+               void *data;
+       } *children;
+       /*
+        * The struct pollfd is logically part of *children,
+        * but the system call expects it as its own array.
+        */
+       struct pollfd *pfd;
+
+       unsigned shutdown : 1;
+
+       int output_owner;
+       struct strbuf buffered_output; /* of finished children */
+};
+
+static int default_start_failure(struct child_process *cp,
+                                struct strbuf *err,
+                                void *pp_cb,
+                                void *pp_task_cb)
+{
+       int i;
+
+       strbuf_addstr(err, "Starting a child failed:");
+       for (i = 0; cp->argv[i]; i++)
+               strbuf_addf(err, " %s", cp->argv[i]);
+
+       return 0;
+}
+
+static int default_task_finished(int result,
+                                struct child_process *cp,
+                                struct strbuf *err,
+                                void *pp_cb,
+                                void *pp_task_cb)
+{
+       int i;
+
+       if (!result)
+               return 0;
+
+       strbuf_addf(err, "A child failed with return code %d:", result);
+       for (i = 0; cp->argv[i]; i++)
+               strbuf_addf(err, " %s", cp->argv[i]);
+
+       return 0;
+}
+
+static void kill_children(struct parallel_processes *pp, int signo)
+{
+       int i, n = pp->max_processes;
+
+       for (i = 0; i < n; i++)
+               if (pp->children[i].state == GIT_CP_WORKING)
+                       kill(pp->children[i].process.pid, signo);
+}
+
+static struct parallel_processes *pp_for_signal;
+
+static void handle_children_on_signal(int signo)
+{
+       kill_children(pp_for_signal, signo);
+       sigchain_pop(signo);
+       raise(signo);
+}
+
+static void pp_init(struct parallel_processes *pp,
+                   int n,
+                   get_next_task_fn get_next_task,
+                   start_failure_fn start_failure,
+                   task_finished_fn task_finished,
+                   void *data)
+{
+       int i;
+
+       if (n < 1)
+               n = online_cpus();
+
+       pp->max_processes = n;
+
+       trace_printf("run_processes_parallel: preparing to run up to %d tasks", n);
+
+       pp->data = data;
+       if (!get_next_task)
+               die("BUG: you need to specify a get_next_task function");
+       pp->get_next_task = get_next_task;
+
+       pp->start_failure = start_failure ? start_failure : default_start_failure;
+       pp->task_finished = task_finished ? task_finished : default_task_finished;
+
+       pp->nr_processes = 0;
+       pp->output_owner = 0;
+       pp->shutdown = 0;
+       pp->children = xcalloc(n, sizeof(*pp->children));
+       pp->pfd = xcalloc(n, sizeof(*pp->pfd));
+       strbuf_init(&pp->buffered_output, 0);
+
+       for (i = 0; i < n; i++) {
+               strbuf_init(&pp->children[i].err, 0);
+               child_process_init(&pp->children[i].process);
+               pp->pfd[i].events = POLLIN | POLLHUP;
+               pp->pfd[i].fd = -1;
+       }
+
+       pp_for_signal = pp;
+       sigchain_push_common(handle_children_on_signal);
+}
+
+static void pp_cleanup(struct parallel_processes *pp)
+{
+       int i;
+
+       trace_printf("run_processes_parallel: done");
+       for (i = 0; i < pp->max_processes; i++) {
+               strbuf_release(&pp->children[i].err);
+               child_process_clear(&pp->children[i].process);
+       }
+
+       free(pp->children);
+       free(pp->pfd);
+
+       /*
+        * When get_next_task added messages to the buffer in its last
+        * iteration, the buffered output is non empty.
+        */
+       fputs(pp->buffered_output.buf, stderr);
+       strbuf_release(&pp->buffered_output);
+
+       sigchain_pop_common();
+}
+
+/* returns
+ *  0 if a new task was started.
+ *  1 if no new jobs was started (get_next_task ran out of work, non critical
+ *    problem with starting a new command)
+ * <0 no new job was started, user wishes to shutdown early. Use negative code
+ *    to signal the children.
+ */
+static int pp_start_one(struct parallel_processes *pp)
+{
+       int i, code;
+
+       for (i = 0; i < pp->max_processes; i++)
+               if (pp->children[i].state == GIT_CP_FREE)
+                       break;
+       if (i == pp->max_processes)
+               die("BUG: bookkeeping is hard");
+
+       code = pp->get_next_task(&pp->children[i].process,
+                                &pp->children[i].err,
+                                pp->data,
+                                &pp->children[i].data);
+       if (!code) {
+               strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
+               strbuf_reset(&pp->children[i].err);
+               return 1;
+       }
+       pp->children[i].process.err = -1;
+       pp->children[i].process.stdout_to_stderr = 1;
+       pp->children[i].process.no_stdin = 1;
+
+       if (start_command(&pp->children[i].process)) {
+               code = pp->start_failure(&pp->children[i].process,
+                                        &pp->children[i].err,
+                                        pp->data,
+                                        &pp->children[i].data);
+               strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
+               strbuf_reset(&pp->children[i].err);
+               if (code)
+                       pp->shutdown = 1;
+               return code;
+       }
+
+       pp->nr_processes++;
+       pp->children[i].state = GIT_CP_WORKING;
+       pp->pfd[i].fd = pp->children[i].process.err;
+       return 0;
+}
+
+static void pp_buffer_stderr(struct parallel_processes *pp, int output_timeout)
+{
+       int i;
+
+       while ((i = poll(pp->pfd, pp->max_processes, output_timeout)) < 0) {
+               if (errno == EINTR)
+                       continue;
+               pp_cleanup(pp);
+               die_errno("poll");
+       }
+
+       /* Buffer output from all pipes. */
+       for (i = 0; i < pp->max_processes; i++) {
+               if (pp->children[i].state == GIT_CP_WORKING &&
+                   pp->pfd[i].revents & (POLLIN | POLLHUP)) {
+                       int n = strbuf_read_once(&pp->children[i].err,
+                                                pp->children[i].process.err, 0);
+                       if (n == 0) {
+                               close(pp->children[i].process.err);
+                               pp->children[i].state = GIT_CP_WAIT_CLEANUP;
+                       } else if (n < 0)
+                               if (errno != EAGAIN)
+                                       die_errno("read");
+               }
+       }
+}
+
+static void pp_output(struct parallel_processes *pp)
+{
+       int i = pp->output_owner;
+       if (pp->children[i].state == GIT_CP_WORKING &&
+           pp->children[i].err.len) {
+               fputs(pp->children[i].err.buf, stderr);
+               strbuf_reset(&pp->children[i].err);
+       }
+}
+
+static int pp_collect_finished(struct parallel_processes *pp)
+{
+       int i, code;
+       int n = pp->max_processes;
+       int result = 0;
+
+       while (pp->nr_processes > 0) {
+               for (i = 0; i < pp->max_processes; i++)
+                       if (pp->children[i].state == GIT_CP_WAIT_CLEANUP)
+                               break;
+               if (i == pp->max_processes)
+                       break;
+
+               code = finish_command(&pp->children[i].process);
+
+               code = pp->task_finished(code, &pp->children[i].process,
+                                        &pp->children[i].err, pp->data,
+                                        &pp->children[i].data);
+
+               if (code)
+                       result = code;
+               if (code < 0)
+                       break;
+
+               pp->nr_processes--;
+               pp->children[i].state = GIT_CP_FREE;
+               pp->pfd[i].fd = -1;
+               child_process_init(&pp->children[i].process);
+
+               if (i != pp->output_owner) {
+                       strbuf_addbuf(&pp->buffered_output, &pp->children[i].err);
+                       strbuf_reset(&pp->children[i].err);
+               } else {
+                       fputs(pp->children[i].err.buf, stderr);
+                       strbuf_reset(&pp->children[i].err);
+
+                       /* Output all other finished child processes */
+                       fputs(pp->buffered_output.buf, stderr);
+                       strbuf_reset(&pp->buffered_output);
+
+                       /*
+                        * Pick next process to output live.
+                        * NEEDSWORK:
+                        * For now we pick it randomly by doing a round
+                        * robin. Later we may want to pick the one with
+                        * the most output or the longest or shortest
+                        * running process time.
+                        */
+                       for (i = 0; i < n; i++)
+                               if (pp->children[(pp->output_owner + i) % n].state == GIT_CP_WORKING)
+                                       break;
+                       pp->output_owner = (pp->output_owner + i) % n;
+               }
+       }
+       return result;
+}
+
+int run_processes_parallel(int n,
+                          get_next_task_fn get_next_task,
+                          start_failure_fn start_failure,
+                          task_finished_fn task_finished,
+                          void *pp_cb)
+{
+       int i, code;
+       int output_timeout = 100;
+       int spawn_cap = 4;
+       struct parallel_processes pp;
+
+       pp_init(&pp, n, get_next_task, start_failure, task_finished, pp_cb);
+       while (1) {
+               for (i = 0;
+                   i < spawn_cap && !pp.shutdown &&
+                   pp.nr_processes < pp.max_processes;
+                   i++) {
+                       code = pp_start_one(&pp);
+                       if (!code)
+                               continue;
+                       if (code < 0) {
+                               pp.shutdown = 1;
+                               kill_children(&pp, -code);
+                       }
+                       break;
+               }
+               if (!pp.nr_processes)
+                       break;
+               pp_buffer_stderr(&pp, output_timeout);
+               pp_output(&pp);
+               code = pp_collect_finished(&pp);
+               if (code) {
+                       pp.shutdown = 1;
+                       if (code < 0)
+                               kill_children(&pp, -code);
+               }
+       }
+
+       pp_cleanup(&pp);
+       return 0;
+}
index 12bb26c2a6155750203babfec47b08e8bde0ad27..d5a57f922781de57d8ee6ae56f90af1456ccd5d5 100644 (file)
@@ -122,4 +122,84 @@ int start_async(struct async *async);
 int finish_async(struct async *async);
 int in_async(void);
 
+/**
+ * This callback should initialize the child process and preload the
+ * error channel if desired. The preloading of is useful if you want to
+ * have a message printed directly before the output of the child process.
+ * pp_cb is the callback cookie as passed to run_processes_parallel.
+ * You can store a child process specific callback cookie in pp_task_cb.
+ *
+ * Even after returning 0 to indicate that there are no more processes,
+ * this function will be called again until there are no more running
+ * child processes.
+ *
+ * Return 1 if the next child is ready to run.
+ * Return 0 if there are currently no more tasks to be processed.
+ * To send a signal to other child processes for abortion,
+ * return the negative signal number.
+ */
+typedef int (*get_next_task_fn)(struct child_process *cp,
+                               struct strbuf *err,
+                               void *pp_cb,
+                               void **pp_task_cb);
+
+/**
+ * This callback is called whenever there are problems starting
+ * a new process.
+ *
+ * You must not write to stdout or stderr in this function. Add your
+ * message to the strbuf err instead, which will be printed without
+ * messing up the output of the other parallel processes.
+ *
+ * pp_cb is the callback cookie as passed into run_processes_parallel,
+ * pp_task_cb is the callback cookie as passed into get_next_task_fn.
+ *
+ * Return 0 to continue the parallel processing. To abort return non zero.
+ * To send a signal to other child processes for abortion, return
+ * the negative signal number.
+ */
+typedef int (*start_failure_fn)(struct child_process *cp,
+                               struct strbuf *err,
+                               void *pp_cb,
+                               void *pp_task_cb);
+
+/**
+ * This callback is called on every child process that finished processing.
+ *
+ * You must not write to stdout or stderr in this function. Add your
+ * message to the strbuf err instead, which will be printed without
+ * messing up the output of the other parallel processes.
+ *
+ * pp_cb is the callback cookie as passed into run_processes_parallel,
+ * pp_task_cb is the callback cookie as passed into get_next_task_fn.
+ *
+ * Return 0 to continue the parallel processing.  To abort return non zero.
+ * To send a signal to other child processes for abortion, return
+ * the negative signal number.
+ */
+typedef int (*task_finished_fn)(int result,
+                               struct child_process *cp,
+                               struct strbuf *err,
+                               void *pp_cb,
+                               void *pp_task_cb);
+
+/**
+ * Runs up to n processes at the same time. Whenever a process can be
+ * started, the callback get_next_task_fn is called to obtain the data
+ * required to start another child process.
+ *
+ * The children started via this function run in parallel. Their output
+ * (both stdout and stderr) is routed to stderr in a manner that output
+ * from different tasks does not interleave.
+ *
+ * If start_failure_fn or task_finished_fn are NULL, default handlers
+ * will be used. The default handlers will print an error message on
+ * error without issuing an emergency stop.
+ */
+int run_processes_parallel(int n,
+                          get_next_task_fn,
+                          start_failure_fn,
+                          task_finished_fn,
+                          void *pp_cb);
+
 #endif
index 8c58fa2f4ddaaadb09a63ef5a1937b4282ed988a..80487860c8fc5c79e3ffd4fbe21a0a0ea7e385ca 100644 (file)
@@ -886,7 +886,7 @@ static int sequencer_rollback(struct replay_opts *opts)
        if (!f)
                return error(_("cannot open %s: %s"), git_path_head_file(),
                                                strerror(errno));
-       if (strbuf_getline(&buf, f, '\n')) {
+       if (strbuf_getline_lf(&buf, f)) {
                error(_("cannot read %s: %s"), git_path_head_file(),
                      ferror(f) ?  strerror(errno) : _("unexpected end of file"));
                fclose(f);
diff --git a/setup.c b/setup.c
index d34372520b05a2acee36f02ddc2ef68dde4b65fd..0deb02238ba426144e0b7b077c9f2ad5c7993d23 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -312,6 +312,23 @@ int is_git_directory(const char *suspect)
        return ret;
 }
 
+int is_nonbare_repository_dir(struct strbuf *path)
+{
+       int ret = 0;
+       int gitfile_error;
+       size_t orig_path_len = path->len;
+       assert(orig_path_len != 0);
+       strbuf_complete(path, '/');
+       strbuf_addstr(path, ".git");
+       if (read_gitfile_gently(path->buf, &gitfile_error) || is_git_directory(path->buf))
+               ret = 1;
+       if (gitfile_error == READ_GITFILE_ERR_OPEN_FAILED ||
+           gitfile_error == READ_GITFILE_ERR_READ_FAILED)
+               ret = 1;
+       strbuf_setlen(path, orig_path_len);
+       return ret;
+}
+
 int is_inside_git_dir(void)
 {
        if (inside_git_dir < 0)
@@ -434,17 +451,6 @@ static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
        return ret;
 }
 
-static void update_linked_gitdir(const char *gitfile, const char *gitdir)
-{
-       struct strbuf path = STRBUF_INIT;
-       struct stat st;
-
-       strbuf_addf(&path, "%s/gitdir", gitdir);
-       if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL))
-               write_file(path.buf, "%s", gitfile);
-       strbuf_release(&path);
-}
-
 /*
  * Try to read the location of the git directory from the .git file,
  * return path to git directory if found.
@@ -514,7 +520,6 @@ const char *read_gitfile_gently(const char *path, int *return_error_code)
                error_code = READ_GITFILE_ERR_NOT_A_REPO;
                goto cleanup_return;
        }
-       update_linked_gitdir(path, dir);
        path = real_path(dir);
 
 cleanup_return:
index 73ccd49a465b1cf8b668edf8c13ea75d6b8de718..aab1872b4c95416fc7c8ae9c93cd25f341e2d4c1 100644 (file)
@@ -396,7 +396,7 @@ void add_to_alternates_file(const char *reference)
                struct strbuf line = STRBUF_INIT;
                int found = 0;
 
-               while (strbuf_getline(&line, in, '\n') != EOF) {
+               while (strbuf_getline(&line, in) != EOF) {
                        if (!strcmp(reference, line.buf)) {
                                found = 1;
                                break;
diff --git a/shell.c b/shell.c
index ace62e4b6503d821962242f9cf3bd9af22bc39b9..c5439a63e9678e1dc3dfa7d4e1f2a97c331e54d6 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -88,7 +88,7 @@ static void run_shell(void)
                int count;
 
                fprintf(stderr, "git> ");
-               if (strbuf_getline(&line, stdin, '\n') == EOF) {
+               if (strbuf_getline_lf(&line, stdin) == EOF) {
                        fprintf(stderr, "\n");
                        strbuf_release(&line);
                        break;
index faa375d5d8e7cf6bbba599034308028efaba1e0f..2ac43bbd282492e3c35c6ac5f96b14a541ed74c6 100644 (file)
@@ -50,3 +50,12 @@ void sigchain_push_common(sigchain_fun f)
        sigchain_push(SIGQUIT, f);
        sigchain_push(SIGPIPE, f);
 }
+
+void sigchain_pop_common(void)
+{
+       sigchain_pop(SIGPIPE);
+       sigchain_pop(SIGQUIT);
+       sigchain_pop(SIGTERM);
+       sigchain_pop(SIGHUP);
+       sigchain_pop(SIGINT);
+}
index 618083bce0c66a551fd4d894b31520a67b25bac9..138b20f54b4017c1f38036935f483c628094affb 100644 (file)
@@ -7,5 +7,6 @@ int sigchain_push(int sig, sigchain_fun f);
 int sigchain_pop(int sig);
 
 void sigchain_push_common(sigchain_fun f);
+void sigchain_pop_common(void);
 
 #endif /* SIGCHAIN_H */
index d76f0aed85c4ec6eafdcfd1a8ee2b22d3d20df96..bab316dda8f4946efb9a908f17c98b4db3d21e98 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -384,6 +384,17 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
        return sb->len - oldlen;
 }
 
+ssize_t strbuf_read_once(struct strbuf *sb, int fd, size_t hint)
+{
+       ssize_t cnt;
+
+       strbuf_grow(sb, hint ? hint : 8192);
+       cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
+       if (cnt > 0)
+               strbuf_setlen(sb, sb->len + cnt);
+       return cnt;
+}
+
 #define STRBUF_MAXLINK (2*PATH_MAX)
 
 int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
@@ -501,15 +512,37 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
 }
 #endif
 
-int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
+static int strbuf_getdelim(struct strbuf *sb, FILE *fp, int term)
 {
        if (strbuf_getwholeline(sb, fp, term))
                return EOF;
-       if (sb->buf[sb->len-1] == term)
-               strbuf_setlen(sb, sb->len-1);
+       if (sb->buf[sb->len - 1] == term)
+               strbuf_setlen(sb, sb->len - 1);
        return 0;
 }
 
+int strbuf_getline(struct strbuf *sb, FILE *fp)
+{
+       if (strbuf_getwholeline(sb, fp, '\n'))
+               return EOF;
+       if (sb->buf[sb->len - 1] == '\n') {
+               strbuf_setlen(sb, sb->len - 1);
+               if (sb->len && sb->buf[sb->len - 1] == '\r')
+                       strbuf_setlen(sb, sb->len - 1);
+       }
+       return 0;
+}
+
+int strbuf_getline_lf(struct strbuf *sb, FILE *fp)
+{
+       return strbuf_getdelim(sb, fp, '\n');
+}
+
+int strbuf_getline_nul(struct strbuf *sb, FILE *fp)
+{
+       return strbuf_getdelim(sb, fp, '\0');
+}
+
 int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int term)
 {
        strbuf_reset(sb);
index 7123fca7aff5182b66af6d76991552081139467c..f72fd14c2eaded0399b779150ea1565edd7bf47a 100644 (file)
--- a/strbuf.h
+++ b/strbuf.h
@@ -354,8 +354,8 @@ extern void strbuf_addftime(struct strbuf *sb, const char *fmt, const struct tm
  *
  * NOTE: The buffer is rewound if the read fails. If -1 is returned,
  * `errno` must be consulted, like you would do for `read(3)`.
- * `strbuf_read()`, `strbuf_read_file()` and `strbuf_getline()` has the
- * same behaviour as well.
+ * `strbuf_read()`, `strbuf_read_file()` and `strbuf_getline_*()`
+ * family of functions have the same behaviour as well.
  */
 extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
 
@@ -366,6 +366,14 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
  */
 extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);
 
+/**
+ * Read the contents of a given file descriptor partially by using only one
+ * attempt of xread. The third argument can be used to give a hint about the
+ * file size, to avoid reallocs. Returns the number of new bytes appended to
+ * the sb.
+ */
+extern ssize_t strbuf_read_once(struct strbuf *, int fd, size_t hint);
+
 /**
  * Read the contents of a file, specified by its path. The third argument
  * can be used to give a hint about the file size, to avoid reallocs.
@@ -379,14 +387,31 @@ extern ssize_t strbuf_read_file(struct strbuf *sb, const char *path, size_t hint
 extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);
 
 /**
- * Read a line from a FILE *, overwriting the existing contents
- * of the strbuf. The second argument specifies the line
- * terminator character, typically `'\n'`.
+ * Read a line from a FILE *, overwriting the existing contents of
+ * the strbuf.  The strbuf_getline*() family of functions share
+ * this signature, but have different line termination conventions.
+ *
  * Reading stops after the terminator or at EOF.  The terminator
  * is removed from the buffer before returning.  Returns 0 unless
  * there was nothing left before EOF, in which case it returns `EOF`.
  */
-extern int strbuf_getline(struct strbuf *, FILE *, int);
+typedef int (*strbuf_getline_fn)(struct strbuf *, FILE *);
+
+/* Uses LF as the line terminator */
+extern int strbuf_getline_lf(struct strbuf *sb, FILE *fp);
+
+/* Uses NUL as the line terminator */
+extern int strbuf_getline_nul(struct strbuf *sb, FILE *fp);
+
+/*
+ * Similar to strbuf_getline_lf(), but additionally treats a CR that
+ * comes immediately before the LF as part of the terminator.
+ * This is the most friendly version to be used to read "text" files
+ * that can come from platforms whose native text format is CRLF
+ * terminated.
+ */
+extern int strbuf_getline(struct strbuf *, FILE *);
+
 
 /**
  * Like `strbuf_getline`, but keeps the trailing terminator (if
index 14e76247bf107da916cf100b8078cf10238e6b76..b83939c294782ac59e5c78c8882064a1e272e309 100644 (file)
@@ -12,6 +12,7 @@
 #include "sha1-array.h"
 #include "argv-array.h"
 #include "blob.h"
+#include "thread-utils.h"
 
 static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND;
 static struct string_list changed_submodule_paths;
@@ -610,37 +611,28 @@ static void calculate_changed_submodule_paths(void)
        initialized_fetch_ref_tips = 0;
 }
 
-int fetch_populated_submodules(const struct argv_array *options,
-                              const char *prefix, int command_line_option,
-                              int quiet)
+struct submodule_parallel_fetch {
+       int count;
+       struct argv_array args;
+       const char *work_tree;
+       const char *prefix;
+       int command_line_option;
+       int quiet;
+       int result;
+};
+#define SPF_INIT {0, ARGV_ARRAY_INIT, NULL, NULL, 0, 0, 0}
+
+static int get_next_submodule(struct child_process *cp,
+                             struct strbuf *err, void *data, void **task_cb)
 {
-       int i, result = 0;
-       struct child_process cp = CHILD_PROCESS_INIT;
-       struct argv_array argv = ARGV_ARRAY_INIT;
-       const char *work_tree = get_git_work_tree();
-       if (!work_tree)
-               goto out;
-
-       if (read_cache() < 0)
-               die("index file corrupt");
-
-       argv_array_push(&argv, "fetch");
-       for (i = 0; i < options->argc; i++)
-               argv_array_push(&argv, options->argv[i]);
-       argv_array_push(&argv, "--recurse-submodules-default");
-       /* default value, "--submodule-prefix" and its value are added later */
-
-       cp.env = local_repo_env;
-       cp.git_cmd = 1;
-       cp.no_stdin = 1;
-
-       calculate_changed_submodule_paths();
+       int ret = 0;
+       struct submodule_parallel_fetch *spf = data;
 
-       for (i = 0; i < active_nr; i++) {
+       for (; spf->count < active_nr; spf->count++) {
                struct strbuf submodule_path = STRBUF_INIT;
                struct strbuf submodule_git_dir = STRBUF_INIT;
                struct strbuf submodule_prefix = STRBUF_INIT;
-               const struct cache_entry *ce = active_cache[i];
+               const struct cache_entry *ce = active_cache[spf->count];
                const char *git_dir, *default_argv;
                const struct submodule *submodule;
 
@@ -652,7 +644,7 @@ int fetch_populated_submodules(const struct argv_array *options,
                        submodule = submodule_from_name(null_sha1, ce->name);
 
                default_argv = "yes";
-               if (command_line_option == RECURSE_SUBMODULES_DEFAULT) {
+               if (spf->command_line_option == RECURSE_SUBMODULES_DEFAULT) {
                        if (submodule &&
                            submodule->fetch_recurse !=
                                                RECURSE_SUBMODULES_NONE) {
@@ -675,40 +667,101 @@ int fetch_populated_submodules(const struct argv_array *options,
                                        default_argv = "on-demand";
                                }
                        }
-               } else if (command_line_option == RECURSE_SUBMODULES_ON_DEMAND) {
+               } else if (spf->command_line_option == RECURSE_SUBMODULES_ON_DEMAND) {
                        if (!unsorted_string_list_lookup(&changed_submodule_paths, ce->name))
                                continue;
                        default_argv = "on-demand";
                }
 
-               strbuf_addf(&submodule_path, "%s/%s", work_tree, ce->name);
+               strbuf_addf(&submodule_path, "%s/%s", spf->work_tree, ce->name);
                strbuf_addf(&submodule_git_dir, "%s/.git", submodule_path.buf);
-               strbuf_addf(&submodule_prefix, "%s%s/", prefix, ce->name);
+               strbuf_addf(&submodule_prefix, "%s%s/", spf->prefix, ce->name);
                git_dir = read_gitfile(submodule_git_dir.buf);
                if (!git_dir)
                        git_dir = submodule_git_dir.buf;
                if (is_directory(git_dir)) {
-                       if (!quiet)
-                               printf("Fetching submodule %s%s\n", prefix, ce->name);
-                       cp.dir = submodule_path.buf;
-                       argv_array_push(&argv, default_argv);
-                       argv_array_push(&argv, "--submodule-prefix");
-                       argv_array_push(&argv, submodule_prefix.buf);
-                       cp.argv = argv.argv;
-                       if (run_command(&cp))
-                               result = 1;
-                       argv_array_pop(&argv);
-                       argv_array_pop(&argv);
-                       argv_array_pop(&argv);
+                       child_process_init(cp);
+                       cp->dir = strbuf_detach(&submodule_path, NULL);
+                       cp->env = local_repo_env;
+                       cp->git_cmd = 1;
+                       if (!spf->quiet)
+                               strbuf_addf(err, "Fetching submodule %s%s\n",
+                                           spf->prefix, ce->name);
+                       argv_array_init(&cp->args);
+                       argv_array_pushv(&cp->args, spf->args.argv);
+                       argv_array_push(&cp->args, default_argv);
+                       argv_array_push(&cp->args, "--submodule-prefix");
+                       argv_array_push(&cp->args, submodule_prefix.buf);
+                       ret = 1;
                }
                strbuf_release(&submodule_path);
                strbuf_release(&submodule_git_dir);
                strbuf_release(&submodule_prefix);
+               if (ret) {
+                       spf->count++;
+                       return 1;
+               }
        }
-       argv_array_clear(&argv);
+       return 0;
+}
+
+static int fetch_start_failure(struct child_process *cp,
+                              struct strbuf *err,
+                              void *cb, void *task_cb)
+{
+       struct submodule_parallel_fetch *spf = cb;
+
+       spf->result = 1;
+
+       return 0;
+}
+
+static int fetch_finish(int retvalue, struct child_process *cp,
+                       struct strbuf *err, void *cb, void *task_cb)
+{
+       struct submodule_parallel_fetch *spf = cb;
+
+       if (retvalue)
+               spf->result = 1;
+
+       return 0;
+}
+
+int fetch_populated_submodules(const struct argv_array *options,
+                              const char *prefix, int command_line_option,
+                              int quiet, int max_parallel_jobs)
+{
+       int i;
+       struct submodule_parallel_fetch spf = SPF_INIT;
+
+       spf.work_tree = get_git_work_tree();
+       spf.command_line_option = command_line_option;
+       spf.quiet = quiet;
+       spf.prefix = prefix;
+
+       if (!spf.work_tree)
+               goto out;
+
+       if (read_cache() < 0)
+               die("index file corrupt");
+
+       argv_array_push(&spf.args, "fetch");
+       for (i = 0; i < options->argc; i++)
+               argv_array_push(&spf.args, options->argv[i]);
+       argv_array_push(&spf.args, "--recurse-submodules-default");
+       /* default value, "--submodule-prefix" and its value are added later */
+
+       calculate_changed_submodule_paths();
+       run_processes_parallel(max_parallel_jobs,
+                              get_next_submodule,
+                              fetch_start_failure,
+                              fetch_finish,
+                              &spf);
+
+       argv_array_clear(&spf.args);
 out:
        string_list_clear(&changed_submodule_paths, 1);
-       return result;
+       return spf.result;
 }
 
 unsigned is_submodule_modified(const char *path, int ignore_untracked)
index ddff512109cbf24f0ead87676f1fc8e6cb92f897..e06eaa5ebb30e825fd0721c76e7d194b0b854706 100644 (file)
@@ -32,7 +32,7 @@ void set_config_fetch_recurse_submodules(int value);
 void check_for_new_submodule_commits(unsigned char new_sha1[20]);
 int fetch_populated_submodules(const struct argv_array *options,
                               const char *prefix, int command_line_option,
-                              int quiet);
+                              int quiet, int max_parallel_jobs);
 unsigned is_submodule_modified(const char *path, int ignore_untracked);
 int submodule_uses_gitfile(const char *path);
 int ok_to_remove_submodule(const char *path);
index e9714467d05e57eded6f37c3d5f07b91f63cc9fc..f9f3e5fd82e1b34d87993f750bd05e46e69bd82c 100644 (file)
@@ -98,8 +98,8 @@ then
        test_skip_or_die $GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'"
 fi
 
-HTTPD_VERSION=`$LIB_HTTPD_PATH -v | \
-       sed -n 's/^Server version: Apache\/\([0-9]*\)\..*$/\1/p; q'`
+HTTPD_VERSION=$($LIB_HTTPD_PATH -v | \
+       sed -n 's/^Server version: Apache\/\([0-9]*\)\..*$/\1/p; q')
 
 if test -n "$HTTPD_VERSION"
 then
index ec94cdd657f838020b3bea32ac8b81caf481a4a9..7c1888a27e7fcf090698ec5ac60db72c76fbb807 100755 (executable)
@@ -28,4 +28,8 @@ test_perf 'clean many untracked sub dirs, ignore nested git' '
        git clean -n -q -f -f -d 100000_sub_dirs/
 '
 
+test_perf 'ls-files -o' '
+       git ls-files -o
+'
+
 test_done
index f91bbcfc853a47e0a314160b79fc4816178f1723..295aa5949a13baeb8cafff0a6782f6e49e68a075 100755 (executable)
@@ -87,6 +87,23 @@ test_expect_success 'plain nested in bare through aliased command' '
        check_config bare-ancestor-aliased.git/plain-nested/.git false unset
 '
 
+test_expect_success 'No extra GIT_* on alias scripts' '
+       (
+               env | sed -ne "/^GIT_/s/=.*//p" &&
+               echo GIT_PREFIX &&        # setup.c
+               echo GIT_TEXTDOMAINDIR    # wrapper-for-bin.sh
+       ) | sort | uniq >expected &&
+       cat <<-\EOF >script &&
+       #!/bin/sh
+       env | sed -ne "/^GIT_/s/=.*//p" | sort >actual
+       exit 0
+       EOF
+       chmod 755 script &&
+       git config alias.script \!./script &&
+       ( mkdir sub && cd sub && git script ) &&
+       test_cmp expected actual
+'
+
 test_expect_success 'plain with GIT_WORK_TREE' '
        mkdir plain-wt &&
        test_must_fail env GIT_WORK_TREE="$(pwd)/plain-wt" git init plain-wt
index b3436515044e9d9be04b8164b704106835c31db1..504e5a02a1d930238023bc2fc7a582183f237674 100755 (executable)
@@ -56,21 +56,16 @@ create_gitattributes () {
 }
 
 create_NNO_files () {
-       lfname=$1
-       crlfname=$2
-       lfmixcrlf=$3
-       lfmixcr=$4
-       crlfnul=$5
        for crlf in false true input
        do
                for attr in "" auto text -text lf crlf
                do
                        pfx=NNO_${crlf}_attr_${attr} &&
-                       cp $lfname    ${pfx}_LF.txt &&
-                       cp $crlfname  ${pfx}_CRLF.txt &&
-                       cp $lfmixcrlf ${pfx}_CRLF_mix_LF.txt &&
-                       cp $lfmixcr   ${pfx}_LF_mix_CR.txt &&
-                       cp $crlfnul   ${pfx}_CRLF_nul.txt
+                       cp CRLF_mix_LF ${pfx}_LF.txt &&
+                       cp CRLF_mix_LF ${pfx}_CRLF.txt &&
+                       cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt &&
+                       cp CRLF_mix_LF ${pfx}_LF_mix_CR.txt &&
+                       cp CRLF_mix_LF ${pfx}_CRLF_nul.txt
                done
        done
 }
@@ -96,7 +91,7 @@ commit_check_warn () {
        crlfnul=$7
        pfx=crlf_${crlf}_attr_${attr}
        create_gitattributes "$attr" &&
-       for f in LF CRLF repoMIX LF_mix_CR CRLF_mix_LF LF_nul CRLF_nul
+       for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul CRLF_nul
        do
                fname=${pfx}_$f.txt &&
                cp $f $fname &&
@@ -149,6 +144,27 @@ commit_chk_wrnNNO () {
        '
 }
 
+stats_ascii () {
+       case "$1" in
+       LF)
+               echo lf
+               ;;
+       CRLF)
+               echo crlf
+               ;;
+       CRLF_mix_LF)
+               echo mixed
+               ;;
+       LF_mix_CR|CRLF_nul|LF_nul|CRLF_mix_CR)
+               echo "-text"
+               ;;
+       *)
+               echo error_invalid $1
+               ;;
+       esac
+
+}
+
 check_files_in_repo () {
        crlf=$1
        attr=$2
@@ -203,35 +219,83 @@ checkout_files () {
        create_gitattributes $attr &&
        git config core.autocrlf $crlf &&
        pfx=eol_${eol}_crlf_${crlf}_attr_${attr}_ &&
-       src=crlf_false_attr__ &&
        for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul
        do
-               rm $src$f.txt &&
+               rm crlf_false_attr__$f.txt &&
                if test -z "$eol"; then
-                       git checkout $src$f.txt
+                       git checkout crlf_false_attr__$f.txt
                else
-                       git -c core.eol=$eol checkout $src$f.txt
+                       git -c core.eol=$eol checkout crlf_false_attr__$f.txt
                fi
        done
 
+       test_expect_success "ls-files --eol $lfname ${pfx}LF.txt" '
+               test_when_finished "rm expect actual" &&
+               sort <<-EOF >expect &&
+               i/crlf w/$(stats_ascii $crlfname) crlf_false_attr__CRLF.txt
+               i/mixed w/$(stats_ascii $lfmixcrlf) crlf_false_attr__CRLF_mix_LF.txt
+               i/lf w/$(stats_ascii $lfname) crlf_false_attr__LF.txt
+               i/-text w/$(stats_ascii $lfmixcr) crlf_false_attr__LF_mix_CR.txt
+               i/-text w/$(stats_ascii $crlfnul) crlf_false_attr__CRLF_nul.txt
+               i/-text w/$(stats_ascii $crlfnul) crlf_false_attr__LF_nul.txt
+               EOF
+               git ls-files --eol crlf_false_attr__* |
+               sed -e "s!attr/[^       ]*!!g" -e "s/   / /g" -e "s/  */ /g" |
+               sort >actual &&
+               test_cmp expect actual
+       '
        test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF" "
-               compare_ws_file $pfx $lfname    ${src}LF.txt
+               compare_ws_file $pfx $lfname    crlf_false_attr__LF.txt
        "
        test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF" "
-               compare_ws_file $pfx $crlfname  ${src}CRLF.txt
+               compare_ws_file $pfx $crlfname  crlf_false_attr__CRLF.txt
        "
        test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=CRLF_mix_LF" "
-               compare_ws_file $pfx $lfmixcrlf ${src}CRLF_mix_LF.txt
+               compare_ws_file $pfx $lfmixcrlf crlf_false_attr__CRLF_mix_LF.txt
        "
        test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF_mix_CR" "
-               compare_ws_file $pfx $lfmixcr   ${src}LF_mix_CR.txt
+               compare_ws_file $pfx $lfmixcr   crlf_false_attr__LF_mix_CR.txt
        "
        test_expect_success "checkout core.eol=$eol core.autocrlf=$crlf gitattributes=$attr file=LF_nul" "
-               compare_ws_file $pfx $crlfnul   ${src}LF_nul.txt
+               compare_ws_file $pfx $crlfnul   crlf_false_attr__LF_nul.txt
        "
 }
 
-#######
+# Test control characters
+# NUL SOH CR EOF==^Z
+test_expect_success 'ls-files --eol -o Text/Binary' '
+       test_when_finished "rm expect actual TeBi_*" &&
+       STRT=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA &&
+       STR=$STRT$STRT$STRT$STRT &&
+       printf "${STR}BBB\001" >TeBi_127_S &&
+       printf "${STR}BBBB\001">TeBi_128_S &&
+       printf "${STR}BBB\032" >TeBi_127_E &&
+       printf "\032${STR}BBB" >TeBi_E_127 &&
+       printf "${STR}BBBB\000">TeBi_128_N &&
+       printf "${STR}BBB\012">TeBi_128_L &&
+       printf "${STR}BBB\015">TeBi_127_C &&
+       printf "${STR}BB\015\012" >TeBi_126_CL &&
+       printf "${STR}BB\015\012\015" >TeBi_126_CLC &&
+       sort <<-\EOF >expect &&
+       i/ w/-text TeBi_127_S
+       i/ w/none TeBi_128_S
+       i/ w/none TeBi_127_E
+       i/ w/-text TeBi_E_127
+       i/ w/-text TeBi_128_N
+       i/ w/lf TeBi_128_L
+       i/ w/-text TeBi_127_C
+       i/ w/crlf TeBi_126_CL
+       i/ w/-text TeBi_126_CLC
+       EOF
+       git ls-files --eol -o |
+       sed -n -e "/TeBi_/{s!attr/[     ]*!!g
+       s!      ! !g
+       s!  *! !g
+       p
+       }" | sort >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'setup master' '
        echo >.gitattributes &&
        git checkout -b master &&
@@ -480,4 +544,19 @@ checkout_files    native  true  "lf"      LF    CRLF  CRLF_mix_LF  LF_mix_CR
 checkout_files    native  false "crlf"    CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
 checkout_files    native  true  "crlf"    CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
 
+# Should be the last test case: remove some files from the worktree
+test_expect_success 'ls-files --eol -d -z' '
+       rm crlf_false_attr__CRLF.txt crlf_false_attr__CRLF_mix_LF.txt crlf_false_attr__LF.txt .gitattributes &&
+       cat >expect <<-\EOF &&
+       i/crlf w/ crlf_false_attr__CRLF.txt
+       i/lf w/ .gitattributes
+       i/lf w/ crlf_false_attr__LF.txt
+       i/mixed w/ crlf_false_attr__CRLF_mix_LF.txt
+       EOF
+       git ls-files --eol -d |
+       sed -e "s!attr/[^       ]*!!g" -e "s/   / /g" -e "s/  */ /g" |
+       sort >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 627ef854d5c804c0248a728862fdf9d4ea344568..f0152a7ab4aabd4f47f546c038efcd8503adc9a4 100755 (executable)
@@ -59,6 +59,9 @@ case $(uname -s) in
        ;;
 esac
 
+test_expect_success basename 'test-path-utils basename'
+test_expect_success dirname 'test-path-utils dirname'
+
 norm_path "" ""
 norm_path . ""
 norm_path ./ ""
index 9acf628726fe0c648279fb724f1917435db206f7..12228b4aa6cb6a393a006130b31c73625911cec6 100755 (executable)
@@ -47,4 +47,57 @@ test_expect_success POSIXPERM,SANITY 'unreadable directory in PATH' '
        test_cmp expect actual
 '
 
+cat >expect <<-EOF
+preloaded output of a child
+Hello
+World
+preloaded output of a child
+Hello
+World
+preloaded output of a child
+Hello
+World
+preloaded output of a child
+Hello
+World
+EOF
+
+test_expect_success 'run_command runs in parallel with more jobs available than tasks' '
+       test-run-command run-command-parallel 5 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'run_command runs in parallel with as many jobs as tasks' '
+       test-run-command run-command-parallel 4 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'run_command runs in parallel with more tasks than jobs available' '
+       test-run-command run-command-parallel 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<-EOF
+preloaded output of a child
+asking for a quick stop
+preloaded output of a child
+asking for a quick stop
+preloaded output of a child
+asking for a quick stop
+EOF
+
+test_expect_success 'run_command is asked to abort gracefully' '
+       test-run-command run-command-abort 3 false 2>actual &&
+       test_cmp expect actual
+'
+
+cat >expect <<-EOF
+no further jobs available
+EOF
+
+test_expect_success 'run_command outputs ' '
+       test-run-command run-command-no-jobs 3 sh -c "printf \"%s\n%s\n\" Hello World" 2>actual &&
+       test_cmp expect actual
+'
+
 test_done
index f8457f9d14c90349b0d3b09a3f695cbfafc3cbbf..b7e9b4fc5b365897d80501d1c49d70ad47740acc 100755 (executable)
@@ -35,11 +35,11 @@ test_expect_success \
      GIT_COMMITTER_NAME="Committer Name" \
      GIT_COMMITTER_EMAIL="committer@email" \
      GIT_COMMITTER_DATE="2005-05-26 23:30" \
-     TZ=GMT git commit-tree `cat treeid` >commitid 2>/dev/null'
+     TZ=GMT git commit-tree $(cat treeid) >commitid 2>/dev/null'
 
 test_expect_success \
     'read commit' \
-    'git cat-file commit `cat commitid` >commit'
+    'git cat-file commit $(cat commitid) >commit'
 
 test_expect_success \
     'compare commit' \
index 1f0dff3a0b1cedb95b900a01de972e8a02e29f90..417eecc3af2a30c3544ddd2f83b7ccecc540eaf1 100755 (executable)
@@ -29,7 +29,7 @@ reset_to_sane
 
 test_expect_success 'symbolic-ref refuses bare sha1' '
        echo content >file && git add file && git commit -m one &&
-       test_must_fail git symbolic-ref HEAD `git rev-parse HEAD`
+       test_must_fail git symbolic-ref HEAD $(git rev-parse HEAD)
 '
 reset_to_sane
 
@@ -114,4 +114,19 @@ test_expect_success 'symbolic-ref writes reflog entry' '
        test_cmp expect actual
 '
 
+test_expect_success 'symbolic-ref does not create ref d/f conflicts' '
+       git checkout -b df &&
+       test_commit df &&
+       test_must_fail git symbolic-ref refs/heads/df/conflict refs/heads/df &&
+       git pack-refs --all --prune &&
+       test_must_fail git symbolic-ref refs/heads/df/conflict refs/heads/df
+'
+
+test_expect_success 'symbolic-ref handles existing pointer to invalid name' '
+       head=$(git rev-parse HEAD) &&
+       git symbolic-ref HEAD refs/heads/outer &&
+       git update-ref refs/heads/outer/inner $head &&
+       git symbolic-ref HEAD refs/heads/unrelated
+'
+
 test_done
index b79049f6f606f106e40dfdc241d7a168b10b88cb..c623824b4d0c2bfde08a69c242e4c5340b97abd3 100755 (executable)
@@ -62,18 +62,18 @@ test_expect_success setup '
        git add . &&
 
        test_tick && git commit -m rabbit &&
-       H=`git rev-parse --verify HEAD` &&
-       A=`git rev-parse --verify HEAD:A` &&
-       B=`git rev-parse --verify HEAD:A/B` &&
-       C=`git rev-parse --verify HEAD:C` &&
-       D=`git rev-parse --verify HEAD:A/D` &&
-       E=`git rev-parse --verify HEAD:A/B/E` &&
+       H=$(git rev-parse --verify HEAD) &&
+       A=$(git rev-parse --verify HEAD:A) &&
+       B=$(git rev-parse --verify HEAD:A/B) &&
+       C=$(git rev-parse --verify HEAD:C) &&
+       D=$(git rev-parse --verify HEAD:A/D) &&
+       E=$(git rev-parse --verify HEAD:A/B/E) &&
        check_fsck &&
 
        test_chmod +x C &&
        git add C &&
        test_tick && git commit -m dragon &&
-       L=`git rev-parse --verify HEAD` &&
+       L=$(git rev-parse --verify HEAD) &&
        check_fsck &&
 
        rm -f C A/B/E &&
@@ -81,15 +81,15 @@ test_expect_success setup '
        echo horse >A/G &&
        git add F A/G &&
        test_tick && git commit -a -m sheep &&
-       F=`git rev-parse --verify HEAD:F` &&
-       G=`git rev-parse --verify HEAD:A/G` &&
-       I=`git rev-parse --verify HEAD:A` &&
-       J=`git rev-parse --verify HEAD` &&
+       F=$(git rev-parse --verify HEAD:F) &&
+       G=$(git rev-parse --verify HEAD:A/G) &&
+       I=$(git rev-parse --verify HEAD:A) &&
+       J=$(git rev-parse --verify HEAD) &&
        check_fsck &&
 
        rm -f A/G &&
        test_tick && git commit -a -m monkey &&
-       K=`git rev-parse --verify HEAD` &&
+       K=$(git rev-parse --verify HEAD) &&
        check_fsck &&
 
        check_have A B C D E F G H I J K L &&
@@ -325,4 +325,17 @@ test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' '
        test_cmp expect actual
 '
 
+test_expect_success 'no segfaults for reflog containing non-commit sha1s' '
+       git update-ref --create-reflog -m "Creating ref" \
+               refs/tests/tree-in-reflog HEAD &&
+       git update-ref -m "Forcing tree" refs/tests/tree-in-reflog HEAD^{tree} &&
+       git update-ref -m "Restoring to commit" refs/tests/tree-in-reflog HEAD &&
+       git reflog refs/tests/tree-in-reflog
+'
+
+test_expect_failure 'reflog with non-commit entries displays all entries' '
+       git reflog refs/tests/tree-in-reflog >actual &&
+       test_line_count = 3 actual
+'
+
 test_done
index 15973f20945769fd7661cd4b203e96032495a60e..7043ba7947933644f15d086d8bdd95d377c4d265 100755 (executable)
@@ -6,11 +6,11 @@ test_description='tests for ref^{stuff}'
 
 test_expect_success 'setup' '
        echo blob >a-blob &&
-       git tag -a -m blob blob-tag `git hash-object -w a-blob` &&
+       git tag -a -m blob blob-tag $(git hash-object -w a-blob) &&
        mkdir a-tree &&
        echo moreblobs >a-tree/another-blob &&
        git add . &&
-       TREE_SHA1=`git write-tree` &&
+       TREE_SHA1=$(git write-tree) &&
        git tag -a -m tree tree-tag "$TREE_SHA1" &&
        git commit -m Initial &&
        git tag -a -m commit commit-tag &&
index 4a155c8d095fb8ca2c2f88802d3501e01d07ce28..e221167cfbe3fb34cf5aba88cd04f6a1dc9eede5 100755 (executable)
@@ -275,19 +275,19 @@ test_expect_success 'rev-parse --disambiguate' '
 
 test_expect_success 'ambiguous 40-hex ref' '
        TREE=$(git mktree </dev/null) &&
-       REF=`git rev-parse HEAD` &&
+       REF=$(git rev-parse HEAD) &&
        VAL=$(git commit-tree $TREE </dev/null) &&
        git update-ref refs/heads/$REF $VAL &&
-       test `git rev-parse $REF 2>err` = $REF &&
+       test $(git rev-parse $REF 2>err) = $REF &&
        grep "refname.*${REF}.*ambiguous" err
 '
 
 test_expect_success 'ambiguous short sha1 ref' '
        TREE=$(git mktree </dev/null) &&
-       REF=`git rev-parse --short HEAD` &&
+       REF=$(git rev-parse --short HEAD) &&
        VAL=$(git commit-tree $TREE </dev/null) &&
        git update-ref refs/heads/$REF $VAL &&
-       test `git rev-parse $REF 2>err` = $VAL &&
+       test $(git rev-parse $REF 2>err) = $VAL &&
        grep "refname.*${REF}.*ambiguous" err
 '
 
index 193d55c3f4486ce3515b261df0c7edf9b3e3fcbb..8aef49f23624305a62047da4bc2fd66e6a03b0e5 100755 (executable)
@@ -55,7 +55,7 @@ test_expect_success 'disable split index' '
 EOF
        test_cmp ls-files.expect ls-files.actual &&
 
-       BASE=`test-dump-split-index .git/index | grep "^own" | sed "s/own/base/"` &&
+       BASE=$(test-dump-split-index .git/index | grep "^own" | sed "s/own/base/") &&
        test-dump-split-index .git/index | sed "/^own/d" >actual &&
        cat >expect <<EOF &&
 not a split index
index 300f8bf25c34cf4ea4e011d1daa525285ca94c5a..c5501b008c8f56ac0712d9f475ebc460a0d4eea4 100755 (executable)
@@ -19,4 +19,43 @@ test_expect_success 'checkout master from invalid HEAD' '
        git checkout master --
 '
 
+test_expect_success 'checkout notices failure to lock HEAD' '
+       test_when_finished "rm -f .git/HEAD.lock" &&
+       >.git/HEAD.lock &&
+       test_must_fail git checkout -b other
+'
+
+test_expect_success 'create ref directory/file conflict scenario' '
+       git update-ref refs/heads/outer/inner master &&
+
+       # do not rely on symbolic-ref to get a known state,
+       # as it may use the same code we are testing
+       reset_to_df () {
+               echo "ref: refs/heads/outer" >.git/HEAD
+       }
+'
+
+test_expect_success 'checkout away from d/f HEAD (unpacked, to branch)' '
+       reset_to_df &&
+       git checkout master
+'
+
+test_expect_success 'checkout away from d/f HEAD (unpacked, to detached)' '
+       reset_to_df &&
+       git checkout --detach master
+'
+
+test_expect_success 'pack refs' '
+       git pack-refs --all --prune
+'
+
+test_expect_success 'checkout away from d/f HEAD (packed, to branch)' '
+       reset_to_df &&
+       git checkout master
+'
+
+test_expect_success 'checkout away from d/f HEAD (packed, to detached)' '
+       reset_to_df &&
+       git checkout --detach master
+'
 test_done
index 369417498946fcebb901d8593bb584f3767b1e67..0a804dab634d0a72bfabd8826d0cb38e1b4f7dbc 100755 (executable)
@@ -123,10 +123,10 @@ test_expect_success 'checkout from a bare repo without "add"' '
 test_expect_success 'checkout with grafts' '
        test_when_finished rm .git/info/grafts &&
        test_commit abc &&
-       SHA1=`git rev-parse HEAD` &&
+       SHA1=$(git rev-parse HEAD) &&
        test_commit def &&
        test_commit xyz &&
-       echo "`git rev-parse HEAD` $SHA1" >.git/info/grafts &&
+       echo "$(git rev-parse HEAD) $SHA1" >.git/info/grafts &&
        cat >expected <<-\EOF &&
        xyz
        abc
index 4d0d0a35156ee1a7604f0ea719e93d3f765a2f91..22f2c730ae8dbf995605e9134eeb2a5bc84065db 100755 (executable)
@@ -23,7 +23,7 @@ git update-index symlink'
 
 test_expect_success \
 'the index entry must still be a symbolic link' '
-case "`git ls-files --stage --cached symlink`" in
+case "$(git ls-files --stage --cached symlink)" in
 120000" "*symlink) echo pass;;
 *) echo fail; git ls-files --stage --cached symlink; (exit 1);;
 esac'
index 88be904c09214586b18f867306f7a8dcf1170cb7..c525656b2c04f8999482496688a0bd47ae8da9e2 100755 (executable)
@@ -65,6 +65,13 @@ test_expect_success '--no-empty-directory hides empty directory' '
        test_cmp expected3 output
 '
 
+test_expect_success 'ls-files --others handles non-submodule .git' '
+       mkdir not-a-submodule &&
+       echo foo >not-a-submodule/.git &&
+       git ls-files -o >output &&
+       test_cmp expected1 output
+'
+
 test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' '
        git init super &&
        git init sub &&
index da257c020fb64d6b8af6b482339afd87f04fea75..3fc484e8c3f8d910f02e409baf7bf1d5682b4f2f 100755 (executable)
@@ -305,29 +305,4 @@ test_expect_success 'ls-files with "**" patterns and no slashes' '
        test_cmp expect actual
 '
 
-test_expect_success 'negative patterns' '
-       git init reinclude &&
-       (
-               cd reinclude &&
-               cat >.gitignore <<-\EOF &&
-               /fooo
-               /foo
-               !foo/bar/bar
-               EOF
-               mkdir fooo &&
-               cat >fooo/.gitignore <<-\EOF &&
-               !/*
-               EOF
-               mkdir -p foo/bar &&
-               touch abc foo/def foo/bar/ghi foo/bar/bar &&
-               git ls-files -o --exclude-standard >../actual &&
-               cat >../expected <<-\EOF &&
-               .gitignore
-               abc
-               foo/bar/bar
-               EOF
-               test_cmp ../expected ../actual
-       )
-'
-
 test_done
index 6224187632b105edf1940023eba4a49523d92fe2..f7b0e599f1124c332a106a3b8df6f304382c2fa4 100755 (executable)
@@ -263,7 +263,7 @@ test_expect_success 'setup 8' '
        test_ln_s_add e a &&
        test_tick &&
        git commit -m "rename a->e, symlink a->e" &&
-       oln=`printf e | git hash-object --stdin`
+       oln=$(printf e | git hash-object --stdin)
 '
 
 test_expect_success 'setup 9' '
index eb73c06a4e1ee826684ee84efa134ee5517023a6..325114f8fee810ac9cf1836f50e060f69b5fe46e 100755 (executable)
@@ -28,7 +28,7 @@ test_expect_success \
      echo Mi >path2/baz/b &&
      find path? \( -type f -o -type l \) -print |
      xargs git update-index --add &&
-     tree=`git write-tree` &&
+     tree=$(git write-tree) &&
      echo $tree'
 
 test_output () {
index 026f9f89d916fdd0547c58aed7bcba7f06850023..425d858938f51bdb8745b28e92c74246e618ef07 100755 (executable)
@@ -35,7 +35,7 @@ test_expect_success 'setup' '
        echo 222 >path3/2.txt &&
        find *.txt path* \( -type f -o -type l \) -print |
        xargs git update-index --add &&
-       tree=`git write-tree` &&
+       tree=$(git write-tree) &&
        echo $tree
 '
 
index d3913f9088950a3ca848b8994abfddfecd3f6706..4261403cf62542e82d40487e47733f586e106a75 100755 (executable)
@@ -176,4 +176,12 @@ test_expect_success 'git branch --points-at option' '
        test_cmp expect actual
 '
 
+test_expect_success 'ambiguous branch/tag not marked' '
+       git tag ambiguous &&
+       git branch ambiguous &&
+       echo "  ambiguous" >expect &&
+       git branch --list ambiguous >actual &&
+       test_cmp expect actual
+'
+
 test_done
index db244d2f8820cf63fd77e91460631009b20e4029..9b182a0c328e9bc6eb1e24a0cbaec47d9fa36b24 100755 (executable)
@@ -27,7 +27,7 @@ SHA1=
 test_expect_success \
     'see if git show-ref works as expected' \
     'git branch a &&
-     SHA1=`cat .git/refs/heads/a` &&
+     SHA1=$(cat .git/refs/heads/a) &&
      echo "$SHA1 refs/heads/a" >expect &&
      git show-ref a >result &&
      test_cmp expect result'
index cd70274ea51ac5c5ba6669495b944da5b7b97431..2d200fdf36c62c12cbbf2a964d3489edef401257 100755 (executable)
@@ -83,6 +83,16 @@ test_expect_success 'edit existing notes' '
        test_must_fail git notes show HEAD^
 '
 
+test_expect_success 'show notes from treeish' '
+       test "b3" = "$(git notes --ref commits^{tree} show)" &&
+       test "b4" = "$(git notes --ref commits@{1} show)"
+'
+
+test_expect_success 'cannot edit notes from non-ref' '
+       test_must_fail git notes --ref commits^{tree} edit &&
+       test_must_fail git notes --ref commits@{1} edit
+'
+
 test_expect_success 'cannot "git notes add -m" where notes already exists' '
        test_must_fail git notes add -m "b2" &&
        test_path_is_missing .git/NOTES_EDITMSG &&
index 24d82b49bbea6535f486b2ffdb4a5a761f736dcc..19aed7ec953b3d384a2f44ee2bae7fd4c92fc5fa 100755 (executable)
@@ -18,7 +18,9 @@ test_expect_success setup '
        git notes add -m "Notes on 1st commit" 1st &&
        git notes add -m "Notes on 2nd commit" 2nd &&
        git notes add -m "Notes on 3rd commit" 3rd &&
-       git notes add -m "Notes on 4th commit" 4th
+       git notes add -m "Notes on 4th commit" 4th &&
+       # Copy notes to remote-notes
+       git fetch . refs/notes/*:refs/remote-notes/origin/*
 '
 
 commit_sha1=$(git rev-parse 1st^{commit})
@@ -66,7 +68,9 @@ test_expect_success 'verify initial notes (x)' '
 '
 
 cp expect_notes_x expect_notes_y
+cp expect_notes_x expect_notes_v
 cp expect_log_x expect_log_y
+cp expect_log_x expect_log_v
 
 test_expect_success 'fail to merge empty notes ref into empty notes ref (z => y)' '
        test_must_fail git -c "core.notesRef=refs/notes/y" notes merge z
@@ -84,16 +88,12 @@ test_expect_success 'fail to merge into various non-notes refs' '
        test_must_fail git -c "core.notesRef=refs/notes/foo^{bar" notes merge x
 '
 
-test_expect_success 'fail to merge various non-note-trees' '
-       git config core.notesRef refs/notes/y &&
-       test_must_fail git notes merge refs/notes &&
-       test_must_fail git notes merge refs/notes/ &&
-       test_must_fail git notes merge refs/notes/dir &&
-       test_must_fail git notes merge refs/notes/dir/ &&
-       test_must_fail git notes merge refs/heads/master &&
-       test_must_fail git notes merge x: &&
-       test_must_fail git notes merge x:foo &&
-       test_must_fail git notes merge foo^{bar
+test_expect_success 'merge non-notes ref into empty notes ref (remote-notes/origin/x => v)' '
+       git config core.notesRef refs/notes/v &&
+       git notes merge refs/remote-notes/origin/x &&
+       verify_notes v &&
+       # refs/remote-notes/origin/x and v should point to the same notes commit
+       test "$(git rev-parse refs/remote-notes/origin/x)" = "$(git rev-parse refs/notes/v)"
 '
 
 test_expect_success 'merge notes into empty notes ref (x => y)' '
index 3968020e648091e907fde6efe9aeb5ce66753670..1f5122b632fb9d7829e7b5f28c2a2971e9ea04e7 100755 (executable)
@@ -67,7 +67,7 @@ test_expect_success 'rebase --skip with --merge' '
 '
 
 test_expect_success 'merge and reference trees equal' '
-       test -z "`git diff-tree skip-merge skip-reference`"
+       test -z "$(git diff-tree skip-merge skip-reference)"
 '
 
 test_expect_success 'moved back to branch correctly' '
index b7dff09d0656930332f347bd3106d1473015abd0..9cce5ae8815a11e3453f5669b0592f7f7659009b 100755 (executable)
@@ -77,7 +77,7 @@ test_expect_success setup '
 
 test_expect_success 'cherry-pick -x inserts blank line after one line subject' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-one-line^0` &&
+       sha1=$(git rev-parse mesg-one-line^0) &&
        git cherry-pick -x mesg-one-line &&
        cat <<-EOF >expect &&
                $mesg_one_line
@@ -114,7 +114,7 @@ test_expect_success 'cherry-pick -s inserts blank line after non-conforming foot
 
 test_expect_success 'cherry-pick -x inserts blank line when conforming footer not found' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-no-footer^0` &&
+       sha1=$(git rev-parse mesg-no-footer^0) &&
        git cherry-pick -x mesg-no-footer &&
        cat <<-EOF >expect &&
                $mesg_no_footer
@@ -139,7 +139,7 @@ test_expect_success 'cherry-pick -s inserts blank line when conforming footer no
 
 test_expect_success 'cherry-pick -x -s inserts blank line when conforming footer not found' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-no-footer^0` &&
+       sha1=$(git rev-parse mesg-no-footer^0) &&
        git cherry-pick -x -s mesg-no-footer &&
        cat <<-EOF >expect &&
                $mesg_no_footer
@@ -164,7 +164,7 @@ test_expect_success 'cherry-pick -s adds sob when last sob doesnt match committe
 
 test_expect_success 'cherry-pick -x -s adds sob when last sob doesnt match committer' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-with-footer^0` &&
+       sha1=$(git rev-parse mesg-with-footer^0) &&
        git cherry-pick -x -s mesg-with-footer &&
        cat <<-EOF >expect &&
                $mesg_with_footer
@@ -187,7 +187,7 @@ test_expect_success 'cherry-pick -s refrains from adding duplicate trailing sob'
 
 test_expect_success 'cherry-pick -x -s adds sob even when trailing sob exists for committer' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-with-footer-sob^0` &&
+       sha1=$(git rev-parse mesg-with-footer-sob^0) &&
        git cherry-pick -x -s mesg-with-footer-sob &&
        cat <<-EOF >expect &&
                $mesg_with_footer_sob
@@ -200,7 +200,7 @@ test_expect_success 'cherry-pick -x -s adds sob even when trailing sob exists fo
 
 test_expect_success 'cherry-pick -x treats "(cherry picked from..." line as part of footer' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-with-cherry-footer^0` &&
+       sha1=$(git rev-parse mesg-with-cherry-footer^0) &&
        git cherry-pick -x mesg-with-cherry-footer &&
        cat <<-EOF >expect &&
                $mesg_with_cherry_footer
@@ -223,7 +223,7 @@ test_expect_success 'cherry-pick -s treats "(cherry picked from..." line as part
 
 test_expect_success 'cherry-pick -x -s treats "(cherry picked from..." line as part of footer' '
        pristine_detach initial &&
-       sha1=`git rev-parse mesg-with-cherry-footer^0` &&
+       sha1=$(git rev-parse mesg-with-cherry-footer^0) &&
        git cherry-pick -x -s mesg-with-cherry-footer &&
        cat <<-EOF >expect &&
                $mesg_with_cherry_footer
index 9d90d2c935bcd3d4dc745287a9068395cb2b3d93..2e47a2bfd8c99988d536483a0c01d8b81396c5b5 100755 (executable)
@@ -115,7 +115,7 @@ test_expect_success '"rm" command printed' '
        git add test-file &&
        git commit -m "add file for rm test" &&
        git rm test-file > rm-output &&
-       test `grep "^rm " rm-output | wc -l` = 1 &&
+       test $(grep "^rm " rm-output | wc -l) = 1 &&
        rm -f test-file rm-output &&
        git commit -m "remove file from rm test"
 '
@@ -125,7 +125,7 @@ test_expect_success '"rm" command suppressed with --quiet' '
        git add test-file &&
        git commit -m "add file for rm --quiet test" &&
        git rm --quiet test-file > rm-output &&
-       test `wc -l < rm-output` = 0 &&
+       test $(wc -l < rm-output) = 0 &&
        rm -f test-file rm-output &&
        git commit -m "remove file from rm --quiet test"
 '
index f7ff1f555d473ec1e7bd0f32d8d3c29426adc9f0..f14a6653565cede5ad9d43e47e71eaf98f58839f 100755 (executable)
@@ -25,7 +25,7 @@ test_expect_success \
         echo foo >xfoo1 &&
         chmod 755 xfoo1 &&
         git add xfoo1 &&
-        case "`git ls-files --stage xfoo1`" in
+        case "$(git ls-files --stage xfoo1)" in
         100644" "*xfoo1) echo pass;;
         *) echo fail; git ls-files --stage xfoo1; (exit 1);;
         esac'
@@ -33,7 +33,7 @@ test_expect_success \
 test_expect_success 'git add: filemode=0 should not get confused by symlink' '
        rm -f xfoo1 &&
        test_ln_s_add foo xfoo1 &&
-       case "`git ls-files --stage xfoo1`" in
+       case "$(git ls-files --stage xfoo1)" in
        120000" "*xfoo1) echo pass;;
        *) echo fail; git ls-files --stage xfoo1; (exit 1);;
        esac
@@ -45,7 +45,7 @@ test_expect_success \
         echo foo >xfoo2 &&
         chmod 755 xfoo2 &&
         git update-index --add xfoo2 &&
-        case "`git ls-files --stage xfoo2`" in
+        case "$(git ls-files --stage xfoo2)" in
         100644" "*xfoo2) echo pass;;
         *) echo fail; git ls-files --stage xfoo2; (exit 1);;
         esac'
@@ -53,7 +53,7 @@ test_expect_success \
 test_expect_success 'git add: filemode=0 should not get confused by symlink' '
        rm -f xfoo2 &&
        test_ln_s_add foo xfoo2 &&
-       case "`git ls-files --stage xfoo2`" in
+       case "$(git ls-files --stage xfoo2)" in
        120000" "*xfoo2) echo pass;;
        *) echo fail; git ls-files --stage xfoo2; (exit 1);;
        esac
@@ -63,7 +63,7 @@ test_expect_success \
        'git update-index --add: Test that executable bit is not used...' \
        'git config core.filemode 0 &&
         test_ln_s_add xfoo2 xfoo3 &&   # runs git update-index --add
-        case "`git ls-files --stage xfoo3`" in
+        case "$(git ls-files --stage xfoo3)" in
         120000" "*xfoo3) echo pass;;
         *) echo fail; git ls-files --stage xfoo3; (exit 1);;
         esac'
@@ -173,14 +173,14 @@ test_expect_success 'git add with filemode=0, symlinks=0 prefers stage 2 over st
 
 test_expect_success 'git add --refresh' '
        >foo && git add foo && git commit -a -m "commit all" &&
-       test -z "`git diff-index HEAD -- foo`" &&
+       test -z "$(git diff-index HEAD -- foo)" &&
        git read-tree HEAD &&
-       case "`git diff-index HEAD -- foo`" in
+       case "$(git diff-index HEAD -- foo)" in
        :100644" "*"M   foo") echo pass;;
        *) echo fail; (exit 1);;
        esac &&
        git add --refresh -- foo &&
-       test -z "`git diff-index HEAD -- foo`"
+       test -z "$(git diff-index HEAD -- foo)"
 '
 
 test_expect_success 'git add --refresh with pathspec' '
index 646c4750ec6d3003379da34ee29f247d45cf5b57..3b99434e3e6f534efe44850fef3d1d77c04f5856 100755 (executable)
@@ -1445,4 +1445,19 @@ test_expect_success 'From line has expected format' '
        test_cmp from filtered
 '
 
+test_expect_success 'format-patch format.outputDirectory option' '
+       test_config format.outputDirectory patches &&
+       rm -fr patches &&
+       git format-patch master..side &&
+       test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l)
+'
+
+test_expect_success 'format-patch -o overrides format.outputDirectory' '
+       test_config format.outputDirectory patches &&
+       rm -fr patches patchset &&
+       git format-patch master..side -o patchset &&
+       test_path_is_missing patches &&
+       test_path_is_dir patchset
+'
+
 test_done
index c0460bb0e59c42de179fc6cbe0f3702a3b538a8e..43dd474a12e97945d38de00f7ab99f30d73490ea 100755 (executable)
@@ -68,6 +68,12 @@ test_expect_success POSIXPERM,SANITY 'unreadable orderfile' '
        test_must_fail git diff -Ounreadable_file --name-only HEAD^..HEAD
 '
 
+test_expect_success "orderfile using option from subdir with --output" '
+       mkdir subdir &&
+       git -C subdir diff -O../order_file_1 --output ../actual --name-only HEAD^..HEAD &&
+       test_cmp expect_1 actual
+'
+
 for i in 1 2
 do
        test_expect_success "orderfile using option ($i)" '
index 7600a3e3e8f4fab47abd68a29bb06defb6bbce02..f5e63670faa0c5acc38adc17d32ae66b59d66b64 100755 (executable)
@@ -120,6 +120,12 @@ test_expect_success !MINGW 'shortlog from non-git directory' '
        test_cmp expect out
 '
 
+test_expect_success !MINGW 'shortlog can read --format=raw output' '
+       git log --format=raw HEAD >log &&
+       GIT_DIR=non-existing git shortlog -w <log >out &&
+       test_cmp expect out
+'
+
 test_expect_success 'shortlog should add newline when input line matches wraplen' '
        cat >expect <<\EOF &&
 A U Thor (2):
@@ -172,22 +178,6 @@ test_expect_success !MINGW 'shortlog encoding' '
        git shortlog HEAD~2.. > out &&
 test_cmp expect out'
 
-test_expect_success 'shortlog ignores commits with missing authors' '
-       git commit --allow-empty -m normal &&
-       git commit --allow-empty -m soon-to-be-broken &&
-       git cat-file commit HEAD >commit.tmp &&
-       sed "/^author/d" commit.tmp >broken.tmp &&
-       commit=$(git hash-object -w -t commit --stdin <broken.tmp) &&
-       git update-ref HEAD $commit &&
-       cat >expect <<-\EOF &&
-       A U Thor (1):
-             normal
-
-       EOF
-       git shortlog HEAD~2.. >actual &&
-       test_cmp expect actual
-'
-
 test_expect_success 'shortlog with revision pseudo options' '
        git shortlog --all &&
        git shortlog --branches &&
index e97cfb2ab838fc9d9ecf1a7d207d6316e11a63f5..85b3df5e339b668688873c27244c458443bb6e6a 100755 (executable)
@@ -9,9 +9,9 @@ test_description='git mailinfo and git mailsplit test'
 
 test_expect_success 'split sample box' \
        'git mailsplit -o. "$TEST_DIRECTORY"/t5100/sample.mbox >last &&
-       last=`cat last` &&
+       last=$(cat last) &&
        echo total is $last &&
-       test `cat last` = 17'
+       test $(cat last) = 17'
 
 check_mailinfo () {
        mail=$1 opt=$2
@@ -23,7 +23,7 @@ check_mailinfo () {
 }
 
 
-for mail in `echo 00*`
+for mail in 00*
 do
        test_expect_success "mailinfo $mail" '
                check_mailinfo $mail "" &&
@@ -47,11 +47,11 @@ test_expect_success 'split box with rfc2047 samples' \
        'mkdir rfc2047 &&
        git mailsplit -orfc2047 "$TEST_DIRECTORY"/t5100/rfc2047-samples.mbox \
          >rfc2047/last &&
-       last=`cat rfc2047/last` &&
+       last=$(cat rfc2047/last) &&
        echo total is $last &&
-       test `cat rfc2047/last` = 11'
+       test $(cat rfc2047/last) = 11'
 
-for mail in `echo rfc2047/00*`
+for mail in rfc2047/00*
 do
        test_expect_success "mailinfo $mail" '
                git mailinfo -u $mail-msg $mail-patch <$mail >$mail-info &&
index 20c1961515a02e3411d02a5656bf8a9dc6b198de..fc2be63e02d85682cd24457ee646c8c626ca967a 100755 (executable)
@@ -8,7 +8,7 @@ test_description='git pack-object
 '
 . ./test-lib.sh
 
-TRASH=`pwd`
+TRASH=$(pwd)
 
 test_expect_success \
     'setup' \
@@ -20,8 +20,8 @@ test_expect_success \
      test-genrandom "seed b" 2097152 > b_big &&
      git update-index --add a a_big b b_big c &&
      cat c >d && echo foo >>d && git update-index --add d &&
-     tree=`git write-tree` &&
-     commit=`git commit-tree $tree </dev/null` && {
+     tree=$(git write-tree) &&
+     commit=$(git commit-tree $tree </dev/null) && {
         echo $tree &&
         echo $commit &&
         git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\)       .*/\\1/"
@@ -29,7 +29,7 @@ test_expect_success \
         git diff-tree --root -p $commit &&
         while read object
         do
-           t=`git cat-file -t $object` &&
+           t=$(git cat-file -t $object) &&
            git cat-file $t $object || return 1
         done <obj-list
      } >expect'
@@ -147,7 +147,7 @@ test_expect_success \
         git diff-tree --root -p $commit &&
         while read object
         do
-           t=`git cat-file -t $object` &&
+           t=$(git cat-file -t $object) &&
            git cat-file $t $object || return 1
         done <obj-list
     } >current &&
@@ -162,7 +162,7 @@ test_expect_success \
         git diff-tree --root -p $commit &&
         while read object
         do
-           t=`git cat-file -t $object` &&
+           t=$(git cat-file -t $object) &&
            git cat-file $t $object || return 1
         done <obj-list
     } >current &&
@@ -177,7 +177,7 @@ test_expect_success \
         git diff-tree --root -p $commit &&
         while read object
         do
-           t=`git cat-file -t $object` &&
+           t=$(git cat-file -t $object) &&
            git cat-file $t $object || return 1
         done <obj-list
     } >current &&
@@ -252,8 +252,8 @@ test_expect_success \
 
 test_expect_success \
     'verify-pack catches a corrupted sum of the index file itself' \
-    'l=`wc -c <test-3.idx` &&
-     l=`expr $l - 20` &&
+    'l=$(wc -c <test-3.idx) &&
+     l=$(expr $l - 20) &&
      cat test-1-${packname_1}.pack >test-3.pack &&
      printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l &&
      if git verify-pack test-3.pack
index 2fc5af6007c75b7789cf2a91163939e24e00ac09..cae8c2e8822ccc1e464e3f5b71c99c1f6b1c2323 100755 (executable)
@@ -16,12 +16,12 @@ test_expect_success \
          git update-index --add $i || return 1
      done &&
      echo d >d && cat c >>d && git update-index --add d &&
-     tree=`git write-tree` &&
-     commit1=`git commit-tree $tree </dev/null` &&
+     tree=$(git write-tree) &&
+     commit1=$(git commit-tree $tree </dev/null) &&
      git update-ref HEAD $commit1 &&
      git repack -a -d &&
-     test "`git count-objects`" = "0 objects, 0 kilobytes" &&
-     pack1=`ls .git/objects/pack/*.pack` &&
+     test "$(git count-objects)" = "0 objects, 0 kilobytes" &&
+     pack1=$(ls .git/objects/pack/*.pack) &&
      test -f "$pack1"'
 
 test_expect_success \
@@ -43,11 +43,11 @@ test_expect_success \
     'repack -a -d, packedGit{WindowSize,Limit} == 1 page' \
     'git config core.packedGitWindowSize 512 &&
      git config core.packedGitLimit 512 &&
-     commit2=`git commit-tree $tree -p $commit1 </dev/null` &&
+     commit2=$(git commit-tree $tree -p $commit1 </dev/null) &&
      git update-ref HEAD $commit2 &&
      git repack -a -d &&
-     test "`git count-objects`" = "0 objects, 0 kilobytes" &&
-     pack2=`ls .git/objects/pack/*.pack` &&
+     test "$(git count-objects)" = "0 objects, 0 kilobytes" &&
+     pack2=$(ls .git/objects/pack/*.pack) &&
      test -f "$pack2" &&
      test "$pack1" \!= "$pack2"'
 
index 3dc5ec4dd331c152754f3c9480042103d5d9f290..c2fc584dac3d7e96748866dd0a4ae31f7cae3fc2 100755 (executable)
@@ -14,21 +14,21 @@ test_expect_success \
      i=1 &&
      while test $i -le 100
      do
-         iii=`printf '%03i' $i`
+         iii=$(printf '%03i' $i)
          test-genrandom "bar" 200 > wide_delta_$iii &&
          test-genrandom "baz $iii" 50 >> wide_delta_$iii &&
          test-genrandom "foo"$i 100 > deep_delta_$iii &&
-         test-genrandom "foo"`expr $i + 1` 100 >> deep_delta_$iii &&
-         test-genrandom "foo"`expr $i + 2` 100 >> deep_delta_$iii &&
+         test-genrandom "foo"$(expr $i + 1) 100 >> deep_delta_$iii &&
+         test-genrandom "foo"$(expr $i + 2) 100 >> deep_delta_$iii &&
          echo $iii >file_$iii &&
          test-genrandom "$iii" 8192 >>file_$iii &&
          git update-index --add file_$iii deep_delta_$iii wide_delta_$iii &&
-         i=`expr $i + 1` || return 1
+         i=$(expr $i + 1) || return 1
      done &&
      { echo 101 && test-genrandom 100 8192; } >file_101 &&
      git update-index --add file_101 &&
-     tree=`git write-tree` &&
-     commit=`git commit-tree $tree </dev/null` && {
+     tree=$(git write-tree) &&
+     commit=$(git commit-tree $tree </dev/null) && {
         echo $tree &&
         git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\)       .*/\\1/"
      } >obj-list &&
@@ -152,10 +152,10 @@ test_expect_success \
     '[index v1] 2) create a stealth corruption in a delta base reference' \
     '# This test assumes file_101 is a delta smaller than 16 bytes.
      # It should be against file_100 but we substitute its base for file_099
-     sha1_101=`git hash-object file_101` &&
-     sha1_099=`git hash-object file_099` &&
-     offs_101=`index_obj_offset 1.idx $sha1_101` &&
-     nr_099=`index_obj_nr 1.idx $sha1_099` &&
+     sha1_101=$(git hash-object file_101) &&
+     sha1_099=$(git hash-object file_099) &&
+     offs_101=$(index_obj_offset 1.idx $sha1_101) &&
+     nr_099=$(index_obj_nr 1.idx $sha1_099) &&
      chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
      dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \
         if=".git/objects/pack/pack-${pack1}.idx" \
@@ -193,10 +193,10 @@ test_expect_success \
     '[index v2] 2) create a stealth corruption in a delta base reference' \
     '# This test assumes file_101 is a delta smaller than 16 bytes.
      # It should be against file_100 but we substitute its base for file_099
-     sha1_101=`git hash-object file_101` &&
-     sha1_099=`git hash-object file_099` &&
-     offs_101=`index_obj_offset 1.idx $sha1_101` &&
-     nr_099=`index_obj_nr 1.idx $sha1_099` &&
+     sha1_101=$(git hash-object file_101) &&
+     sha1_099=$(git hash-object file_099) &&
+     offs_101=$(index_obj_offset 1.idx $sha1_101) &&
+     nr_099=$(index_obj_nr 1.idx $sha1_099) &&
      chmod +w ".git/objects/pack/pack-${pack1}.pack" &&
      dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \
         if=".git/objects/pack/pack-${pack1}.idx" \
@@ -222,11 +222,11 @@ test_expect_success \
     'rm -f .git/objects/pack/* &&
      git index-pack --index-version=2 --stdin < "test-1-${pack1}.pack" &&
      git verify-pack ".git/objects/pack/pack-${pack1}.pack" &&
-     obj=`git hash-object file_001` &&
-     nr=`index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj` &&
+     obj=$(git hash-object file_001) &&
+     nr=$(index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj) &&
      chmod +w ".git/objects/pack/pack-${pack1}.idx" &&
      printf xxxx | dd of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \
-        bs=1 count=4 seek=$((8 + 256 * 4 + `wc -l <obj-list` * 20 + $nr * 4)) &&
+        bs=1 count=4 seek=$((8 + 256 * 4 + $(wc -l <obj-list) * 20 + $nr * 4)) &&
      ( while read obj
        do git cat-file -p $obj >/dev/null || exit 1
        done <obj-list ) &&
index 663b02bbb13cf6bee3d59ea350d5f42add687d7b..5940ce2084a6e9cc935a0e5784ff8b6bff8e035d 100755 (executable)
@@ -32,23 +32,23 @@ create_test_files() {
 create_new_pack() {
     rm -rf .git &&
     git init &&
-    blob_1=`git hash-object -t blob -w file_1` &&
-    blob_2=`git hash-object -t blob -w file_2` &&
-    blob_3=`git hash-object -t blob -w file_3` &&
-    pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
-          git pack-objects $@ .git/objects/pack/pack` &&
+    blob_1=$(git hash-object -t blob -w file_1) &&
+    blob_2=$(git hash-object -t blob -w file_2) &&
+    blob_3=$(git hash-object -t blob -w file_3) &&
+    pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" |
+          git pack-objects $@ .git/objects/pack/pack) &&
     pack=".git/objects/pack/pack-${pack}" &&
     git verify-pack -v ${pack}.pack
 }
 
 do_repack() {
-    pack=`printf "$blob_1\n$blob_2\n$blob_3\n" |
-          git pack-objects $@ .git/objects/pack/pack` &&
+    pack=$(printf "$blob_1\n$blob_2\n$blob_3\n" |
+          git pack-objects $@ .git/objects/pack/pack) &&
     pack=".git/objects/pack/pack-${pack}"
 }
 
 do_corrupt_object() {
-    ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
+    ofs=$(git show-index < ${pack}.idx | grep $1 | cut -f1 -d" ") &&
     ofs=$(($ofs + $2)) &&
     chmod +w ${pack}.pack &&
     dd of=${pack}.pack bs=1 conv=notrunc seek=$ofs &&
index def203c7243c099e1359b9a0c44f22a07c06cb37..133b5842b1aee8e8e00eb0ca7e1b2d32ff4a4c9a 100755 (executable)
@@ -266,7 +266,7 @@ EOF
 '
 
 test_expect_success 'prune .git/shallow' '
-       SHA1=`echo hi|git commit-tree HEAD^{tree}` &&
+       SHA1=$(echo hi|git commit-tree HEAD^{tree}) &&
        echo $SHA1 >.git/shallow &&
        git prune --dry-run >out &&
        grep $SHA1 .git/shallow &&
index 21517c70cd49ab91ab267544311d8c33173e3c3e..f314ad50791142b42c5f2807b5f086bbe9e1caad 100755 (executable)
@@ -3,20 +3,20 @@
 test_description='git pack-object --include-tag'
 . ./test-lib.sh
 
-TRASH=`pwd`
+TRASH=$(pwd)
 
 test_expect_success setup '
        echo c >d &&
        git update-index --add d &&
-       tree=`git write-tree` &&
-       commit=`git commit-tree $tree </dev/null` &&
+       tree=$(git write-tree) &&
+       commit=$(git commit-tree $tree </dev/null) &&
        echo "object $commit" >sig &&
        echo "type commit" >>sig &&
        echo "tag mytag" >>sig &&
        echo "tagger $(git var GIT_COMMITTER_IDENT)" >>sig &&
        echo >>sig &&
        echo "our test tag" >>sig &&
-       tag=`git mktag <sig` &&
+       tag=$(git mktag <sig) &&
        rm d sig &&
        git update-ref refs/tags/mytag $tag && {
                echo $tree &&
index 3a9b77576fb57828cd574017883c7920c2d91aa3..e5f83bf5e412bc3304009408a58663d7b94dac02 100755 (executable)
@@ -14,7 +14,7 @@ test_description='Testing multi_ack pack fetching'
 add () {
        name=$1 &&
        text="$@" &&
-       branch=`echo $name | sed -e 's/^\(.\).*$/\1/'` &&
+       branch=$(echo $name | sed -e 's/^\(.\).*$/\1/') &&
        parents="" &&
 
        shift &&
@@ -50,18 +50,18 @@ pull_to_client () {
                        case "$heads" in *B*)
                            echo $BTIP > .git/refs/heads/B;;
                        esac &&
-                       git symbolic-ref HEAD refs/heads/`echo $heads \
-                               | sed -e "s/^\(.\).*$/\1/"` &&
+                       git symbolic-ref HEAD refs/heads/$(echo $heads \
+                               | sed -e "s/^\(.\).*$/\1/") &&
 
                        git fsck --full &&
 
                        mv .git/objects/pack/pack-* . &&
-                       p=`ls -1 pack-*.pack` &&
+                       p=$(ls -1 pack-*.pack) &&
                        git unpack-objects <$p &&
                        git fsck --full &&
 
-                       idx=`echo pack-*.idx` &&
-                       pack_count=`git show-index <$idx | wc -l` &&
+                       idx=$(echo pack-*.idx) &&
+                       pack_count=$(git show-index <$idx | wc -l) &&
                        test $pack_count = $count &&
                        rm -f pack-*
                )
@@ -132,13 +132,13 @@ test_expect_success 'single given branch clone' '
 
 test_expect_success 'clone shallow depth 1' '
        git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 &&
-       test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 1
+       test "$(git --git-dir=shallow0/.git rev-list --count HEAD)" = 1
 '
 
 test_expect_success 'clone shallow depth 1 with fsck' '
        git config --global fetch.fsckobjects true &&
        git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0fsck &&
-       test "`git --git-dir=shallow0fsck/.git rev-list --count HEAD`" = 1 &&
+       test "$(git --git-dir=shallow0fsck/.git rev-list --count HEAD)" = 1 &&
        git config --global --unset fetch.fsckobjects
 '
 
@@ -147,7 +147,7 @@ test_expect_success 'clone shallow' '
 '
 
 test_expect_success 'clone shallow depth count' '
-       test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 2
+       test "$(git --git-dir=shallow/.git rev-list --count HEAD)" = 2
 '
 
 test_expect_success 'clone shallow object count' '
@@ -273,7 +273,7 @@ test_expect_success 'additional simple shallow deepenings' '
 '
 
 test_expect_success 'clone shallow depth count' '
-       test "`git --git-dir=shallow/.git rev-list --count HEAD`" = 11
+       test "$(git --git-dir=shallow/.git rev-list --count HEAD)" = 11
 '
 
 test_expect_success 'clone shallow object count' '
index dfaf9d9f68939f0c39a512c478265b4aa227c973..1a8e3b81c815cfb92b7025a12d8c703f2ffc54e9 100755 (executable)
@@ -85,7 +85,7 @@ test_expect_success C_LOCALE_OUTPUT 'check remote-tracking' '
 test_expect_success 'remote forces tracking branches' '
        (
                cd test &&
-               case `git config remote.second.fetch` in
+               case $(git config remote.second.fetch) in
                +*) true ;;
                 *) false ;;
                esac
index 530b01678e5c9cfc1aed2fe2c6fcd96b9a09a90d..83d5558c0ef0496e16e7c9f7a69cddc99cd11d86 100755 (executable)
@@ -20,7 +20,7 @@ update_repos() {
 }
 
 repo_fetched() {
-       if test "`git log -1 --pretty=format:%s $1 --`" = "`cat mark`"; then
+       if test "$(git log -1 --pretty=format:%s $1 --)" = "$(cat mark)"; then
                echo >&2 "repo was fetched: $1"
                return 0
        fi
index 0ba9db08847255d28e3e185d18b68703fb0755dc..9203a6507fa8df75ef187c129f750921caf19951 100755 (executable)
@@ -7,7 +7,7 @@ test_description='Per branch config variables affects "git fetch".
 
 . ./test-lib.sh
 
-D=`pwd`
+D=$(pwd)
 
 test_bundle_object_count () {
        git verify-pack -v "$1" >verify.out &&
@@ -64,8 +64,8 @@ test_expect_success "fetch test" '
        cd two &&
        git fetch &&
        test -f .git/refs/heads/one &&
-       mine=`git rev-parse refs/heads/one` &&
-       his=`cd ../one && git rev-parse refs/heads/master` &&
+       mine=$(git rev-parse refs/heads/one) &&
+       his=$(cd ../one && git rev-parse refs/heads/master) &&
        test "z$mine" = "z$his"
 '
 
@@ -75,8 +75,8 @@ test_expect_success "fetch test for-merge" '
        git fetch &&
        test -f .git/refs/heads/two &&
        test -f .git/refs/heads/one &&
-       master_in_two=`cd ../two && git rev-parse master` &&
-       one_in_two=`cd ../two && git rev-parse one` &&
+       master_in_two=$(cd ../two && git rev-parse master) &&
+       one_in_two=$(cd ../two && git rev-parse one) &&
        {
                echo "$one_in_two       "
                echo "$master_in_two    not-for-merge"
@@ -708,4 +708,17 @@ test_expect_success 'fetching a one-level ref works' '
        )
 '
 
+test_expect_success 'fetching with auto-gc does not lock up' '
+       write_script askyesno <<-\EOF &&
+       echo "$*" &&
+       false
+       EOF
+       git clone "file://$D" auto-gc &&
+       test_commit test2 &&
+       cd auto-gc &&
+       git config gc.autoPackLimit 1 &&
+       GIT_ASK_YESNO="$D/askyesno" git fetch >fetch.out 2>&1 &&
+       ! grep "Should I try again" fetch.out
+'
+
 test_done
index aadaac515e086a7f87c6d06a0313fe7b77d11f92..819b9ddd0f917a21e3edf7122f99cfb04f4b7a8f 100755 (executable)
@@ -163,4 +163,49 @@ test_expect_success 'overrides work between mixed transfer/upload-pack hideRefs'
        grep refs/tags/magic actual
 '
 
+test_expect_success 'ls-remote --symref' '
+       cat >expect <<-\EOF &&
+       ref: refs/heads/master  HEAD
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        HEAD
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/master
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/remotes/origin/HEAD
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/remotes/origin/master
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/tags/mark
+       EOF
+       git ls-remote --symref >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'ls-remote with filtered symref (refname)' '
+       cat >expect <<-\EOF &&
+       ref: refs/heads/master  HEAD
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        HEAD
+       EOF
+       git ls-remote --symref . HEAD >actual &&
+       test_cmp expect actual
+'
+
+test_expect_failure 'ls-remote with filtered symref (--heads)' '
+       git symbolic-ref refs/heads/foo refs/tags/mark &&
+       cat >expect <<-\EOF &&
+       ref: refs/tags/mark     refs/heads/foo
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/foo
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/master
+       EOF
+       git ls-remote --symref --heads . >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'ls-remote --symref omits filtered-out matches' '
+       cat >expect <<-\EOF &&
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/foo
+       1bd44cb9d13204b0fe1958db0082f5028a16eb3a        refs/heads/master
+       EOF
+       git ls-remote --symref --heads . >actual &&
+       test_cmp expect actual &&
+       git ls-remote --symref . "refs/heads/*" >actual &&
+       test_cmp expect actual
+'
+
+
 test_done
index dbb927dec8ea9f40e8e106f416c276f1b6a07868..36b0dbc01cffc06aefb180179965ccbaa9c983d8 100755 (executable)
@@ -128,8 +128,8 @@ do
        case "$cmd" in
        '' | '#'*) continue ;;
        esac
-       test=`echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g'`
-       pfx=`printf "%04d" $test_count`
+       test=$(echo "$cmd" | sed -e 's|[/ ][/ ]*|_|g')
+       pfx=$(printf "%04d" $test_count)
        expect_f="$TEST_DIRECTORY/t5515/fetch.$test"
        actual_f="$pfx-fetch.$test"
        expect_r="$TEST_DIRECTORY/t5515/refs.$test"
index 0a87e195eac3a70ecca9e9a5750655774a686b1d..26b2cafc4795baa8b9377c767e4453079826c34f 100755 (executable)
@@ -16,7 +16,7 @@ This test checks the following functionality:
 
 . ./test-lib.sh
 
-D=`pwd`
+D=$(pwd)
 
 mk_empty () {
        repo_name="$1"
@@ -422,7 +422,7 @@ test_expect_success 'push tag with non-existent, incomplete dest' '
 test_expect_success 'push sha1 with non-existent, incomplete dest' '
 
        mk_test testrepo &&
-       test_must_fail git push testrepo `git rev-parse master`:foo
+       test_must_fail git push testrepo $(git rev-parse master):foo
 
 '
 
index 12a5dfb17e0a0bd4d0d9636ff13bf44999f78e36..02f160aae0c414411572a99a148d2b039c24fdd3 100755 (executable)
@@ -4,7 +4,7 @@ test_description='pushing to a mirror repository'
 
 . ./test-lib.sh
 
-D=`pwd`
+D=$(pwd)
 
 invert () {
        if "$@"; then
index a0013ee32f1940e32b4038d6cc9a39b218d794f1..c952d5ef5c4e4d4f3be8759f7aa326a70c36c421 100755 (executable)
@@ -326,6 +326,16 @@ test_expect_success 'pull.rebase=preserve rebases and merges keep-merge' '
        test "$(git rev-parse HEAD^2)" = "$(git rev-parse keep-merge)"
 '
 
+test_expect_success 'pull.rebase=interactive' '
+       write_script "$TRASH_DIRECTORY/fake-editor" <<-\EOF &&
+       echo I was here >fake.out &&
+       false
+       EOF
+       test_set_editor "$TRASH_DIRECTORY/fake-editor" &&
+       test_must_fail git pull --rebase=interactive . copy &&
+       test "I was here" = "$(cat fake.out)"
+'
+
 test_expect_success 'pull.rebase=invalid fails' '
        git reset --hard before-preserve-rebase &&
        test_config pull.rebase invalid &&
index 8e9b204e02a3d204af08463d2229ca0f319cdc42..bcff460d0a2ba2b6b9965e7bff58bc26033231ab 100755 (executable)
@@ -54,7 +54,7 @@ test_expect_success SYMLINKS 'pulling from real subdir' '
 # git rev-parse --show-cdup printed a path relative to
 # clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup
 # used the correct .git, but when the git pull shell script did
-# "cd `git rev-parse --show-cdup`", it ended up in the wrong
+# "cd $(git rev-parse --show-cdup)", it ended up in the wrong
 # directory.  A POSIX shell's "cd" works a little differently
 # than chdir() in C; "cd -P" is much closer to chdir().
 #
index a4532b00d6cbf791a6654b00742138728d4bf66d..1241146227aead97022ade343152347bc911444c 100755 (executable)
@@ -16,7 +16,8 @@ add_upstream_commit() {
                git add subfile &&
                git commit -m new subfile &&
                head2=$(git rev-parse --short HEAD) &&
-               echo "From $pwd/submodule" > ../expect.err &&
+               echo "Fetching submodule submodule" > ../expect.err &&
+               echo "From $pwd/submodule" >> ../expect.err &&
                echo "   $head1..$head2  master     -> origin/master" >> ../expect.err
        ) &&
        (
@@ -27,6 +28,7 @@ add_upstream_commit() {
                git add deepsubfile &&
                git commit -m new deepsubfile &&
                head2=$(git rev-parse --short HEAD) &&
+               echo "Fetching submodule submodule/subdir/deepsubmodule" >> ../expect.err
                echo "From $pwd/deepsubmodule" >> ../expect.err &&
                echo "   $head1..$head2  master     -> origin/master" >> ../expect.err
        )
@@ -56,9 +58,7 @@ test_expect_success setup '
        (
                cd downstream &&
                git submodule update --init --recursive
-       ) &&
-       echo "Fetching submodule submodule" > expect.out &&
-       echo "Fetching submodule submodule/subdir/deepsubmodule" >> expect.out
+       )
 '
 
 test_expect_success "fetch --recurse-submodules recurses into submodules" '
@@ -67,10 +67,21 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" '
                cd downstream &&
                git fetch --recurse-submodules >../actual.out 2>../actual.err
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
+test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" '
+       add_upstream_commit &&
+       (
+               cd downstream &&
+               GIT_TRACE=$(pwd)/../trace.out git fetch --recurse-submodules -j2 2>../actual.err
+       ) &&
+       test_must_be_empty actual.out &&
+       test_i18ncmp expect.err actual.err &&
+       grep "2 tasks" trace.out
+'
+
 test_expect_success "fetch alone only fetches superproject" '
        add_upstream_commit &&
        (
@@ -96,7 +107,7 @@ test_expect_success "using fetchRecurseSubmodules=true in .gitmodules recurses i
                git config -f .gitmodules submodule.submodule.fetchRecurseSubmodules true &&
                git fetch >../actual.out 2>../actual.err
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -127,7 +138,7 @@ test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setti
                git config --unset -f .gitmodules submodule.submodule.fetchRecurseSubmodules &&
                git config --unset submodule.submodule.fetchRecurseSubmodules
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -140,13 +151,22 @@ test_expect_success "--quiet propagates to submodules" '
        ! test -s actual.err
 '
 
+test_expect_success "--quiet propagates to parallel submodules" '
+       (
+               cd downstream &&
+               git fetch --recurse-submodules -j 2 --quiet  >../actual.out 2>../actual.err
+       ) &&
+       ! test -s actual.out &&
+       ! test -s actual.err
+'
+
 test_expect_success "--dry-run propagates to submodules" '
        add_upstream_commit &&
        (
                cd downstream &&
                git fetch --recurse-submodules --dry-run >../actual.out 2>../actual.err
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -155,7 +175,7 @@ test_expect_success "Without --dry-run propagates to submodules" '
                cd downstream &&
                git fetch --recurse-submodules >../actual.out 2>../actual.err
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -166,7 +186,7 @@ test_expect_success "recurseSubmodules=true propagates into submodules" '
                git config fetch.recurseSubmodules true
                git fetch >../actual.out 2>../actual.err
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -180,7 +200,7 @@ test_expect_success "--recurse-submodules overrides config in submodule" '
                ) &&
                git fetch --recurse-submodules >../actual.out 2>../actual.err
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -214,16 +234,15 @@ test_expect_success "Recursion stops when no new submodule commits are fetched"
        git add submodule &&
        git commit -m "new submodule" &&
        head2=$(git rev-parse --short HEAD) &&
-       echo "Fetching submodule submodule" > expect.out.sub &&
        echo "From $pwd/." > expect.err.sub &&
        echo "   $head1..$head2  master     -> origin/master" >>expect.err.sub &&
-       head -2 expect.err >> expect.err.sub &&
+       head -3 expect.err >> expect.err.sub &&
        (
                cd downstream &&
                git fetch >../actual.out 2>../actual.err
        ) &&
        test_i18ncmp expect.err.sub actual.err &&
-       test_i18ncmp expect.out.sub actual.out
+       test_must_be_empty actual.out
 '
 
 test_expect_success "Recursion doesn't happen when new superproject commits don't change any submodules" '
@@ -269,7 +288,7 @@ test_expect_success "Recursion picks up config in submodule" '
                )
        ) &&
        test_i18ncmp expect.err.sub actual.err &&
-       test_i18ncmp expect.out actual.out
+       test_must_be_empty actual.out
 '
 
 test_expect_success "Recursion picks up all submodules when necessary" '
@@ -285,7 +304,8 @@ test_expect_success "Recursion picks up all submodules when necessary" '
                git add subdir/deepsubmodule &&
                git commit -m "new deepsubmodule"
                head2=$(git rev-parse --short HEAD) &&
-               echo "From $pwd/submodule" > ../expect.err.sub &&
+               echo "Fetching submodule submodule" > ../expect.err.sub &&
+               echo "From $pwd/submodule" >> ../expect.err.sub &&
                echo "   $head1..$head2  master     -> origin/master" >> ../expect.err.sub
        ) &&
        head1=$(git rev-parse --short HEAD) &&
@@ -295,13 +315,13 @@ test_expect_success "Recursion picks up all submodules when necessary" '
        echo "From $pwd/." > expect.err.2 &&
        echo "   $head1..$head2  master     -> origin/master" >> expect.err.2 &&
        cat expect.err.sub >> expect.err.2 &&
-       tail -2 expect.err >> expect.err.2 &&
+       tail -3 expect.err >> expect.err.2 &&
        (
                cd downstream &&
                git fetch >../actual.out 2>../actual.err
        ) &&
        test_i18ncmp expect.err.2 actual.err &&
-       test_i18ncmp expect.out actual.out
+       test_must_be_empty actual.out
 '
 
 test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
@@ -317,7 +337,8 @@ test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no ne
                git add subdir/deepsubmodule &&
                git commit -m "new deepsubmodule" &&
                head2=$(git rev-parse --short HEAD) &&
-               echo "From $pwd/submodule" > ../expect.err.sub &&
+               echo Fetching submodule submodule > ../expect.err.sub &&
+               echo "From $pwd/submodule" >> ../expect.err.sub &&
                echo "   $head1..$head2  master     -> origin/master" >> ../expect.err.sub
        ) &&
        (
@@ -335,7 +356,7 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess
        git add submodule &&
        git commit -m "new submodule" &&
        head2=$(git rev-parse --short HEAD) &&
-       tail -2 expect.err > expect.err.deepsub &&
+       tail -3 expect.err > expect.err.deepsub &&
        echo "From $pwd/." > expect.err &&
        echo "   $head1..$head2  master     -> origin/master" >>expect.err &&
        cat expect.err.sub >> expect.err &&
@@ -354,7 +375,7 @@ test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necess
                        git config --unset -f .gitmodules submodule.subdir/deepsubmodule.fetchRecursive
                )
        ) &&
-       test_i18ncmp expect.out actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err actual.err
 '
 
@@ -388,7 +409,7 @@ test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config
        head2=$(git rev-parse --short HEAD) &&
        echo "From $pwd/." > expect.err.2 &&
        echo "   $head1..$head2  master     -> origin/master" >>expect.err.2 &&
-       head -2 expect.err >> expect.err.2 &&
+       head -3 expect.err >> expect.err.2 &&
        (
                cd downstream &&
                git config fetch.recurseSubmodules on-demand &&
@@ -399,7 +420,7 @@ test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config
                cd downstream &&
                git config --unset fetch.recurseSubmodules
        ) &&
-       test_i18ncmp expect.out.sub actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err.2 actual.err
 '
 
@@ -416,7 +437,7 @@ test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' override
        head2=$(git rev-parse --short HEAD) &&
        echo "From $pwd/." > expect.err.2 &&
        echo "   $head1..$head2  master     -> origin/master" >>expect.err.2 &&
-       head -2 expect.err >> expect.err.2 &&
+       head -3 expect.err >> expect.err.2 &&
        (
                cd downstream &&
                git config submodule.submodule.fetchRecurseSubmodules on-demand &&
@@ -427,7 +448,7 @@ test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' override
                cd downstream &&
                git config --unset submodule.submodule.fetchRecurseSubmodules
        ) &&
-       test_i18ncmp expect.out.sub actual.out &&
+       test_must_be_empty actual.out &&
        test_i18ncmp expect.err.2 actual.err
 '
 
index 3932e797f7f60545e6e8c140824a5ca5ee16832a..4f6e32b04c48b7723a2b9dc172cd2104c3349e0b 100755 (executable)
@@ -4,7 +4,7 @@ test_description='errors in upload-pack'
 
 . ./test-lib.sh
 
-D=`pwd`
+D=$(pwd)
 
 corrupt_repo () {
        object_sha1=$(git rev-parse "$1") &&
index 5531bd1af42dac808d64d75a6fc3e848ef968a34..d75ef0ea2b6eb5596ee97b92529d9800411f543c 100755 (executable)
@@ -15,7 +15,7 @@ test_expect_success 'setup remote repo' '
 cat >proxy <<'EOF'
 #!/bin/sh
 echo >&2 "proxying for $*"
-cmd=`"$PERL_PATH" -e '
+cmd=$("$PERL_PATH" -e '
        read(STDIN, $buf, 4);
        my $n = hex($buf) - 4;
        read(STDIN, $buf, $n);
@@ -23,7 +23,7 @@ cmd=`"$PERL_PATH" -e '
        # drop absolute-path on repo name
        $cmd =~ s{ /}{ };
        print $cmd;
-'`
+')
 echo >&2 "Running '$cmd'"
 exec $cmd
 EOF
index a980574682012fbb3f5f7c28a011df980f45c3de..df8d2f095a40f524b8318b98a7c4fb085d8010f4 100755 (executable)
@@ -98,7 +98,7 @@ EOF
 test_expect_success 'fetch something upstream has but hidden by clients shallow boundaries' '
        # the blob "1" is available in .git but hidden by the
        # shallow2/.git/shallow and it should be resent
-       ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` >/dev/null &&
+       ! git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null &&
        echo 1 >1.t &&
        git add 1.t &&
        git commit -m add-1-back &&
@@ -114,7 +114,7 @@ add-1-back
 EOF
        test_cmp expect actual
        ) &&
-       git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` >/dev/null
+       git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null
 
 '
 
index ceee95b8a48455e15769168fe67af17deec7e179..ecbf84d21c807a8d211c2068bd0a5d10deae4758 100755 (executable)
@@ -104,7 +104,7 @@ EOF
 '
 
 test_expect_success 'push from full to shallow' '
-       ! git --git-dir=shallow2/.git cat-file blob `echo 1|git hash-object --stdin` &&
+       ! git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) &&
        commit 1 &&
        git push shallow2/.git +master:refs/remotes/top/master &&
        (
@@ -117,7 +117,7 @@ test_expect_success 'push from full to shallow' '
 3
 EOF
        test_cmp expect actual &&
-       git cat-file blob `echo 1|git hash-object --stdin` >/dev/null
+       git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null
        )
 '
 test_done
index 87a7aa04aeb452c162dc5585efd0ec13195ea80a..64146352ae20e9a5abdcda77be514d0f3264c3b8 100755 (executable)
@@ -132,7 +132,7 @@ test_expect_success 'fetch packed objects' '
 test_expect_success 'fetch notices corrupt pack' '
        cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
        (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
-        p=`ls objects/pack/pack-*.pack` &&
+        p=$(ls objects/pack/pack-*.pack) &&
         chmod u+w $p &&
         printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
        ) &&
@@ -140,14 +140,14 @@ test_expect_success 'fetch notices corrupt pack' '
        (cd repo_bad1.git &&
         git --bare init &&
         test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad1.git &&
-        test 0 = `ls objects/pack/pack-*.pack | wc -l`
+        test 0 = $(ls objects/pack/pack-*.pack | wc -l)
        )
 '
 
 test_expect_success 'fetch notices corrupt idx' '
        cp -R "$HTTPD_DOCUMENT_ROOT_PATH"/repo_pack.git "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
        (cd "$HTTPD_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
-        p=`ls objects/pack/pack-*.idx` &&
+        p=$(ls objects/pack/pack-*.idx) &&
         chmod u+w $p &&
         printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
        ) &&
@@ -155,7 +155,7 @@ test_expect_success 'fetch notices corrupt idx' '
        (cd repo_bad2.git &&
         git --bare init &&
         test_must_fail git --bare fetch $HTTPD_URL/dumb/repo_bad2.git &&
-        test 0 = `ls objects/pack | wc -l`
+        test 0 = $(ls objects/pack | wc -l)
        )
 '
 
index b7e283252d7d73e937ef87096801f2d252e95961..d76269a8fc96a874042cd2e070794e2c56577468 100755 (executable)
@@ -57,7 +57,7 @@ test_expect_success 'prepare pack objects' '
 test_expect_success 'fetch notices corrupt pack' '
        cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
        (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad1.git &&
-        p=`ls objects/pack/pack-*.pack` &&
+        p=$(ls objects/pack/pack-*.pack) &&
         chmod u+w $p &&
         printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
        ) &&
@@ -65,14 +65,14 @@ test_expect_success 'fetch notices corrupt pack' '
        (cd repo_bad1.git &&
         git --bare init &&
         test_must_fail git --bare fetch "$GIT_DAEMON_URL/repo_bad1.git" &&
-        test 0 = `ls objects/pack/pack-*.pack | wc -l`
+        test 0 = $(ls objects/pack/pack-*.pack | wc -l)
        )
 '
 
 test_expect_success 'fetch notices corrupt idx' '
        cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
        (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git &&
-        p=`ls objects/pack/pack-*.idx` &&
+        p=$(ls objects/pack/pack-*.idx) &&
         chmod u+w $p &&
         printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc
        ) &&
@@ -80,7 +80,7 @@ test_expect_success 'fetch notices corrupt idx' '
        (cd repo_bad2.git &&
         git --bare init &&
         test_must_fail git --bare fetch "$GIT_DAEMON_URL/repo_bad2.git" &&
-        test 0 = `ls objects/pack | wc -l`
+        test 0 = $(ls objects/pack | wc -l)
        )
 '
 
index 9b34f3c615df5080085b5f8cf956d2bac099d9d4..669ec9ba811fedeca820c4454b490e975b03bfca 100755 (executable)
@@ -65,6 +65,29 @@ test_expect_success 'clone respects GIT_WORK_TREE' '
 
 '
 
+test_expect_success 'clone from hooks' '
+
+       test_create_repo r0 &&
+       cd r0 &&
+       test_commit initial &&
+       cd .. &&
+       git init r1 &&
+       cd r1 &&
+       cat >.git/hooks/pre-commit <<-\EOF &&
+       #!/bin/sh
+       git clone ../r0 ../r2
+       exit 1
+       EOF
+       chmod u+x .git/hooks/pre-commit &&
+       : >file &&
+       git add file &&
+       test_must_fail git commit -m invoke-hook &&
+       cd .. &&
+       test_cmp r0/.git/HEAD r2/.git/HEAD &&
+       test_cmp r0/initial.t r2/initial.t
+
+'
+
 test_expect_success 'clone creates intermediate directories' '
 
        git clone src long/path/to/dst &&
@@ -221,7 +244,7 @@ test_expect_success 'clone separate gitdir' '
 '
 
 test_expect_success 'clone separate gitdir: output' '
-       echo "gitdir: `pwd`/realgitdir" >expected &&
+       echo "gitdir: $(pwd)/realgitdir" >expected &&
        test_cmp expected dst/.git
 '
 
index dfa1bf79c5690289baeddd4498cb4c84dbd19bbe..4320082b1b8fe709e9462f84d15fec63c54a94d4 100755 (executable)
@@ -6,7 +6,7 @@
 test_description='test clone --reference'
 . ./test-lib.sh
 
-base_dir=`pwd`
+base_dir=$(pwd)
 
 U=$base_dir/UPLOAD_LOG
 
index 5a6e49d18d6f9e6e06409093d9b9f426d70de475..9cd2626dba885b6ebf34ae8efccecf005c95f438 100755 (executable)
@@ -21,7 +21,7 @@ test_valid_repo() {
        test_line_count = 0 fsck.log
 }
 
-base_dir=`pwd`
+base_dir=$(pwd)
 
 test_expect_success 'preparing first repository' \
 'test_create_repo A && cd A &&
index 3d5b418bb48ae9fa50411d1c88bc19b3404f1da1..14e59c5b3e4239c3d41d01f3c6a0d821dfe4e260 100755 (executable)
@@ -15,7 +15,7 @@ make_tree() {
 make_bare() {
        git init --bare "$1" &&
        (cd "$1" &&
-        tree=`git hash-object -w -t tree /dev/null` &&
+        tree=$(git hash-object -w -t tree /dev/null) &&
         commit=$(echo "$1" | git commit-tree $tree) &&
         git update-ref HEAD $commit
        )
index 8efcd130795890c36dfe6c5c630d2be44c6e1699..05ddc69cf2ad9470a125fda47fc450401f94902b 100755 (executable)
@@ -10,15 +10,15 @@ test_expect_success setup '
        echo >subdir/fileB fileB &&
        git add fileA subdir/fileB &&
        git commit -a -m "Initial in one history." &&
-       A0=`git rev-parse --verify HEAD` &&
+       A0=$(git rev-parse --verify HEAD) &&
 
        echo >fileA fileA modified &&
        git commit -a -m "Second in one history." &&
-       A1=`git rev-parse --verify HEAD` &&
+       A1=$(git rev-parse --verify HEAD) &&
 
        echo >subdir/fileB fileB modified &&
        git commit -a -m "Third in one history." &&
-       A2=`git rev-parse --verify HEAD` &&
+       A2=$(git rev-parse --verify HEAD) &&
 
        rm -f .git/refs/heads/master .git/index &&
 
@@ -26,15 +26,15 @@ test_expect_success setup '
        echo >subdir/fileB fileB again &&
        git add fileA subdir/fileB &&
        git commit -a -m "Initial in alternate history." &&
-       B0=`git rev-parse --verify HEAD` &&
+       B0=$(git rev-parse --verify HEAD) &&
 
        echo >fileA fileA modified in alternate history &&
        git commit -a -m "Second in alternate history." &&
-       B1=`git rev-parse --verify HEAD` &&
+       B1=$(git rev-parse --verify HEAD) &&
 
        echo >subdir/fileB fileB modified in alternate history &&
        git commit -a -m "Third in alternate history." &&
-       B2=`git rev-parse --verify HEAD` &&
+       B2=$(git rev-parse --verify HEAD) &&
        : done
 '
 
index 43ad7724845cd0e1523aadd60845f048a6b92ce5..3bf2759eaebd38bca5d37f624144436fc77828eb 100755 (executable)
@@ -27,9 +27,9 @@ test_bisection_diff()
        # Test if bisection size is close to half of list size within
        # tolerance.
        #
-       _bisect_err=`expr $_list_size - $_bisection_size \* 2`
-       test "$_bisect_err" -lt 0 && _bisect_err=`expr 0 - $_bisect_err`
-       _bisect_err=`expr $_bisect_err / 2` ; # floor
+       _bisect_err=$(expr $_list_size - $_bisection_size \* 2)
+       test "$_bisect_err" -lt 0 && _bisect_err=$(expr 0 - $_bisect_err)
+       _bisect_err=$(expr $_bisect_err / 2) ; # floor
 
        test_expect_success \
        "bisection diff $_bisect_option $_head $* <= $_max_diff" \
index 8b146fb432bc7a8dee8eeeb43f2b6b946d51190b..3c73c93ba6eb17db6ea91de7122b8bb7a839e795 100755 (executable)
@@ -6,11 +6,11 @@ test_description='--show-all --parents does not rewrite TREESAME commits'
 
 test_expect_success 'set up --show-all --parents test' '
        test_commit one foo.txt &&
-       commit1=`git rev-list -1 HEAD` &&
+       commit1=$(git rev-list -1 HEAD) &&
        test_commit two bar.txt &&
-       commit2=`git rev-list -1 HEAD` &&
+       commit2=$(git rev-list -1 HEAD) &&
        test_commit three foo.txt &&
-       commit3=`git rev-list -1 HEAD`
+       commit3=$(git rev-list -1 HEAD)
        '
 
 test_expect_success '--parents rewrites TREESAME parents correctly' '
index 190ee903cf6269071809e82d61d6065f1de679c6..20aee43f95ab3cc38b8671a233089873fe374777 100755 (executable)
@@ -346,4 +346,17 @@ test_expect_success 'conflict at EOF without LF resolved by --union' \
         printf "line1\nline2\nline3x\nline3y" >expect.txt &&
         test_cmp expect.txt output.txt'
 
+test_expect_success 'conflict sections match existing line endings' '
+       printf "1\\r\\n2\\r\\n3" >crlf-orig.txt &&
+       printf "1\\r\\n2\\r\\n4" >crlf-diff1.txt &&
+       printf "1\\r\\n2\\r\\n5" >crlf-diff2.txt &&
+       test_must_fail git -c core.eol=crlf merge-file -p \
+               crlf-diff1.txt crlf-orig.txt crlf-diff2.txt >crlf.txt &&
+       test $(tr "\015" Q <crlf.txt | grep "^[<=>].*Q$" | wc -l) = 3 &&
+       test $(tr "\015" Q <crlf.txt | grep "[345]Q$" | wc -l) = 3 &&
+       test_must_fail git -c core.eol=crlf merge-file -p \
+               nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >nolf.txt &&
+       test $(tr "\015" Q <nolf.txt | grep "^[<=>].*Q$" | wc -l) = 0
+'
+
 test_done
index 0f792689174efda55f041b1c6b2aa14f95860772..80777386dc6961b5114a85ea6efd14e066ebc9a4 100755 (executable)
@@ -20,7 +20,7 @@ test_expect_success 'setup (initial)' '
 
 make_text() {
        echo $1: $2
-       for i in `count 20`; do
+       for i in $(count 20); do
                echo $1: $i
        done
        echo $1: $3
index 4d5a25eedfef50c578d776990a8a3ac44064533f..c630aba657e9c78b6dee4a72be34ed3bd03c01ee 100755 (executable)
@@ -351,11 +351,15 @@ test_expect_success 'test --format long' '
        test_cmp expected actual
 '
 
-test_expect_success 'setup a fake editor' '
-       write_script fakeeditor <<-\EOF
+test_expect_success 'setup fake editors' '
+       write_script fakeeditor <<-\EOF &&
                sed -e "s/A U Thor/A fake Thor/" "$1" >"$1.new"
                mv "$1.new" "$1"
        EOF
+       write_script failingfakeeditor <<-\EOF
+               ./fakeeditor "$@"
+               false
+       EOF
 '
 
 test_expect_success '--edit with and without already replaced object' '
@@ -372,7 +376,7 @@ test_expect_success '--edit with and without already replaced object' '
 test_expect_success '--edit and change nothing or command failed' '
        git replace -d "$PARA3" &&
        test_must_fail env GIT_EDITOR=true git replace --edit "$PARA3" &&
-       test_must_fail env GIT_EDITOR="./fakeeditor;false" git replace --edit "$PARA3" &&
+       test_must_fail env GIT_EDITOR="./failingfakeeditor" git replace --edit "$PARA3" &&
        GIT_EDITOR=./fakeeditor git replace --edit "$PARA3" &&
        git replace -l | grep "$PARA3" &&
        git cat-file commit "$PARA3" | grep "A fake Thor"
index e1e1b1fa382fa3ea129450770d575bffdddc47b9..d51595cf6b189a59d271dcc69c3f245b72dcb8f6 100755 (executable)
@@ -7,7 +7,7 @@ test_description='test case exclude pathspec'
 test_expect_success 'setup' '
        for p in file sub/file sub/sub/file sub/file2 sub/sub/sub/file sub2/file; do
                if echo $p | grep /; then
-                       mkdir -p `dirname $p`
+                       mkdir -p $(dirname $p)
                fi &&
                : >$p &&
                git add $p &&
index 03873b09d1a4480549e1b8ab92fc3780fb874d89..19a2823025e794a6adc3f75d65dd175a2021f282 100755 (executable)
@@ -49,11 +49,17 @@ test_atom() {
 }
 
 test_atom head refname refs/heads/master
+test_atom head refname:short master
+test_atom head refname:strip=1 heads/master
+test_atom head refname:strip=2 master
 test_atom head upstream refs/remotes/origin/master
+test_atom head upstream:short origin/master
 test_atom head push refs/remotes/myfork/master
+test_atom head push:short myfork/master
 test_atom head objecttype commit
 test_atom head objectsize 171
 test_atom head objectname $(git rev-parse refs/heads/master)
+test_atom head objectname:short $(git rev-parse --short refs/heads/master)
 test_atom head tree $(git rev-parse refs/heads/master^{tree})
 test_atom head parent ''
 test_atom head numparent 0
@@ -86,11 +92,13 @@ test_atom head contents 'Initial
 test_atom head HEAD '*'
 
 test_atom tag refname refs/tags/testtag
+test_atom tag refname:short testtag
 test_atom tag upstream ''
 test_atom tag push ''
 test_atom tag objecttype tag
 test_atom tag objectsize 154
 test_atom tag objectname $(git rev-parse refs/tags/testtag)
+test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag)
 test_atom tag tree ''
 test_atom tag parent ''
 test_atom tag numparent ''
@@ -126,6 +134,16 @@ test_expect_success 'Check invalid atoms names are errors' '
        test_must_fail git for-each-ref --format="%(INVALID)" refs/heads
 '
 
+test_expect_success 'arguments to :strip must be positive integers' '
+       test_must_fail git for-each-ref --format="%(refname:strip=0)" &&
+       test_must_fail git for-each-ref --format="%(refname:strip=-1)" &&
+       test_must_fail git for-each-ref --format="%(refname:strip=foo)"
+'
+
+test_expect_success 'stripping refnames too far gives an error' '
+       test_must_fail git for-each-ref --format="%(refname:strip=3)"
+'
+
 test_expect_success 'Check format specifiers are ignored in naming date atoms' '
        git for-each-ref --format="%(authordate)" refs/heads &&
        git for-each-ref --format="%(authordate:default) %(authordate)" refs/heads &&
@@ -338,47 +356,14 @@ for i in "--perl --shell" "-s --python" "--python --tcl" "--tcl --perl"; do
        "
 done
 
-cat >expected <<\EOF
-master
-testtag
-EOF
-
-test_expect_success 'Check short refname format' '
-       (git for-each-ref --format="%(refname:short)" refs/heads &&
-       git for-each-ref --format="%(refname:short)" refs/tags) >actual &&
-       test_cmp expected actual
-'
-
-cat >expected <<EOF
-origin/master
-EOF
-
-test_expect_success 'Check short upstream format' '
-       git for-each-ref --format="%(upstream:short)" refs/heads >actual &&
-       test_cmp expected actual
-'
-
 test_expect_success 'setup for upstream:track[short]' '
        test_commit two
 '
 
-cat >expected <<EOF
-[ahead 1]
-EOF
-
-test_expect_success 'Check upstream:track format' '
-       git for-each-ref --format="%(upstream:track)" refs/heads >actual &&
-       test_cmp expected actual
-'
-
-cat >expected <<EOF
->
-EOF
-
-test_expect_success 'Check upstream:trackshort format' '
-       git for-each-ref --format="%(upstream:trackshort)" refs/heads >actual &&
-       test_cmp expected actual
-'
+test_atom head upstream:track '[ahead 1]'
+test_atom head upstream:trackshort '>'
+test_atom head push:track '[ahead 1]'
+test_atom head push:trackshort '>'
 
 test_expect_success 'Check that :track[short] cannot be used with other atoms' '
        test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null &&
@@ -398,21 +383,6 @@ test_expect_success 'Check that :track[short] works when upstream is invalid' '
        test_cmp expected actual
 '
 
-test_expect_success '%(push) supports tracking specifiers, too' '
-       echo "[ahead 1]" >expected &&
-       git for-each-ref --format="%(push:track)" refs/heads >actual &&
-       test_cmp expected actual
-'
-
-cat >expected <<EOF
-$(git rev-parse --short HEAD)
-EOF
-
-test_expect_success 'Check short objectname format' '
-       git for-each-ref --format="%(objectname:short)" refs/heads >actual &&
-       test_cmp expected actual
-'
-
 test_expect_success 'Check for invalid refname format' '
        test_must_fail git for-each-ref --format="%(refname:INVALID)"
 '
index 7b56081137396680df58c887ffe7919d98f6480c..51dd2b4e0e088c11bf359b32eddf353e58ca6d4d 100755 (executable)
@@ -156,11 +156,11 @@ test_expect_success "Michael Cassar's test case" '
        echo b > partA/outline.txt &&
        echo c > papers/unsorted/_another &&
        git add papers partA &&
-       T1=`git write-tree` &&
+       T1=$(git write-tree) &&
 
        git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf &&
 
-       T=`git write-tree` &&
+       T=$(git write-tree) &&
        git ls-tree -r $T | verbose grep partA/outline.txt
 '
 
index 869e0bf0735033f66c5cba44d107f799fc07b112..cb8fbd8e5e03a0ff5a176cc947419c357fd65d99 100755 (executable)
@@ -333,6 +333,14 @@ test_expect_success 'prune empty collapsed merges' '
        test_cmp expect actual
 '
 
+test_expect_success 'prune empty works even without index/tree filters' '
+       git rev-list HEAD >expect &&
+       git commit --allow-empty -m empty &&
+       git filter-branch -f --prune-empty HEAD &&
+       git rev-list HEAD >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success '--remap-to-ancestor with filename filters' '
        git checkout master &&
        git reset --hard A &&
@@ -387,7 +395,7 @@ test_expect_success 'setup submodule' '
        git branch original HEAD
 '
 
-orig_head=`git show-ref --hash --head HEAD`
+orig_head=$(git show-ref --hash --head HEAD)
 
 test_expect_success 'rewrite submodule with another content' '
        git filter-branch --tree-filter "test -d submod && {
@@ -396,7 +404,7 @@ test_expect_success 'rewrite submodule with another content' '
                                         mkdir submod &&
                                         : > submod/file
                                         } || :" HEAD &&
-       test $orig_head != `git show-ref --hash --head HEAD`
+       test $orig_head != $(git show-ref --hash --head HEAD)
 '
 
 test_expect_success 'replace submodule revision' '
@@ -405,7 +413,7 @@ test_expect_success 'replace submodule revision' '
            "if git ls-files --error-unmatch -- submod > /dev/null 2>&1
             then git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 submod
             fi" HEAD &&
-       test $orig_head != `git show-ref --hash --head HEAD`
+       test $orig_head != $(git show-ref --hash --head HEAD)
 '
 
 test_expect_success 'filter commit message without trailing newline' '
index 3dd2f51e49d7e6824382ac415cf64842fa3b757f..cf3469b142d7ab015dca14f4f9898bae784a9e9a 100755 (executable)
@@ -23,8 +23,8 @@ test_expect_success 'listing all tags in an empty tree should succeed' '
 '
 
 test_expect_success 'listing all tags in an empty tree should output nothing' '
-       test `git tag -l | wc -l` -eq 0 &&
-       test `git tag | wc -l` -eq 0
+       test $(git tag -l | wc -l) -eq 0 &&
+       test $(git tag | wc -l) -eq 0
 '
 
 test_expect_success 'looking for a tag in an empty tree should fail' \
@@ -72,8 +72,8 @@ test_expect_success 'listing all tags if one exists should succeed' '
 '
 
 test_expect_success 'listing all tags if one exists should output that tag' '
-       test `git tag -l` = mytag &&
-       test `git tag` = mytag
+       test $(git tag -l) = mytag &&
+       test $(git tag) = mytag
 '
 
 # pattern matching:
@@ -83,7 +83,7 @@ test_expect_success 'listing a tag using a matching pattern should succeed' \
 
 test_expect_success \
        'listing a tag using a matching pattern should output that tag' \
-       'test `git tag -l mytag` = mytag'
+       'test $(git tag -l mytag) = mytag'
 
 # todo: git tag -l now returns always zero, when fixed, change this test
 test_expect_success \
@@ -92,7 +92,7 @@ test_expect_success \
 
 test_expect_success \
        'listing tags using a non-matching pattern should output nothing' \
-       'test `git tag -l xxx | wc -l` -eq 0'
+       'test $(git tag -l xxx | wc -l) -eq 0'
 
 # special cases for creating tags:
 
@@ -102,13 +102,13 @@ test_expect_success \
 
 test_expect_success \
        'trying to create a tag with a non-valid name should fail' '
-       test `git tag -l | wc -l` -eq 1 &&
+       test $(git tag -l | wc -l) -eq 1 &&
        test_must_fail git tag "" &&
        test_must_fail git tag .othertag &&
        test_must_fail git tag "other tag" &&
        test_must_fail git tag "othertag^" &&
        test_must_fail git tag "other~tag" &&
-       test `git tag -l | wc -l` -eq 1
+       test $(git tag -l | wc -l) -eq 1
 '
 
 test_expect_success 'creating a tag using HEAD directly should succeed' '
@@ -1558,4 +1558,12 @@ test_expect_success '--no-merged show unmerged tags' '
        test_cmp expect actual
 '
 
+test_expect_success 'ambiguous branch/tags not marked' '
+       git tag ambiguous &&
+       git branch ambiguous &&
+       echo ambiguous >expect &&
+       git tag -l ambiguous >actual &&
+       test_cmp expect actual
+'
+
 test_done
index 6ea7ac4c418d7ace719910c1730217a1ffe7532f..e4fc5c826c2c02d540c64ac88374f8ad85869023 100755 (executable)
@@ -424,7 +424,7 @@ test_expect_success TTY 'command-specific pager works for external commands' '
        echo "foo:initial" >expect &&
        >actual &&
        test_config pager.external "sed s/^/foo:/ >actual" &&
-       test_terminal git --exec-path="`pwd`" external log --format=%s -1 &&
+       test_terminal git --exec-path="$(pwd)" external log --format=%s -1 &&
        test_cmp expect actual
 '
 
index 0e8d0d42f2f5b1edbc18d46da77c956cd99dadec..a971884cfd8f03de29c978734812ab295fcbb08f 100755 (executable)
@@ -8,10 +8,8 @@ avoid_racy() {
        sleep 1
 }
 
-# It's fine if git update-index returns an error code other than one,
-# it'll be caught in the first test.
 test_lazy_prereq UNTRACKED_CACHE '
-       { git update-index --untracked-cache; ret=$?; } &&
+       { git update-index --test-untracked-cache; ret=$?; } &&
        test $ret -ne 1
 '
 
@@ -20,6 +18,10 @@ if ! test_have_prereq UNTRACKED_CACHE; then
        test_done
 fi
 
+test_expect_success 'core.untrackedCache is unset' '
+       test_must_fail git config --get core.untrackedCache
+'
+
 test_expect_success 'setup' '
        git init worktree &&
        cd worktree &&
@@ -32,13 +34,13 @@ test_expect_success 'setup' '
 
 test_expect_success 'untracked cache is empty' '
        test-dump-untracked-cache >../actual &&
-       cat >../expect <<EOF &&
+       cat >../expect-empty <<EOF &&
 info/exclude 0000000000000000000000000000000000000000
 core.excludesfile 0000000000000000000000000000000000000000
 exclude_per_dir .gitignore
 flags 00000006
 EOF
-       test_cmp ../expect ../actual
+       test_cmp ../expect-empty ../actual
 '
 
 cat >../status.expect <<EOF &&
@@ -508,7 +510,7 @@ EOF
 
 test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
        test-dump-untracked-cache >../actual &&
-       cat >../expect <<EOF &&
+       cat >../expect-from-test-dump <<EOF &&
 info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
 core.excludesfile 0000000000000000000000000000000000000000
 exclude_per_dir .gitignore
@@ -527,7 +529,7 @@ file
 /dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
 two
 EOF
-       test_cmp ../expect ../actual
+       test_cmp ../expect-from-test-dump ../actual
 '
 
 test_expect_success 'test sparse status again with untracked cache and subdir' '
@@ -571,4 +573,77 @@ EOF
        test_cmp ../status.expect ../status.actual
 '
 
+test_expect_success '--no-untracked-cache removes the cache' '
+       git update-index --no-untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       echo "no untracked cache" >../expect-no-uc &&
+       test_cmp ../expect-no-uc ../actual
+'
+
+test_expect_success 'git status does not change anything' '
+       git status &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-no-uc ../actual
+'
+
+test_expect_success 'setting core.untrackedCache to true and using git status creates the cache' '
+       git config core.untrackedCache true &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-no-uc ../actual &&
+       git status &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-from-test-dump ../actual
+'
+
+test_expect_success 'using --no-untracked-cache does not fail when core.untrackedCache is true' '
+       git update-index --no-untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-no-uc ../actual &&
+       git update-index --untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-empty ../actual
+'
+
+test_expect_success 'setting core.untrackedCache to false and using git status removes the cache' '
+       git config core.untrackedCache false &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-empty ../actual &&
+       git status &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-no-uc ../actual
+'
+
+test_expect_success 'using --untracked-cache does not fail when core.untrackedCache is false' '
+       git update-index --untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-empty ../actual
+'
+
+test_expect_success 'setting core.untrackedCache to keep' '
+       git config core.untrackedCache keep &&
+       git update-index --untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-empty ../actual &&
+       git status &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-from-test-dump ../actual &&
+       git update-index --no-untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-no-uc ../actual &&
+       git update-index --force-untracked-cache &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-empty ../actual &&
+       git status &&
+       test-dump-untracked-cache >../actual &&
+       test_cmp ../expect-from-test-dump ../actual
+'
+
+test_expect_success 'test ident field is working' '
+       mkdir ../other_worktree &&
+       cp -R done dthree dtwo four three ../other_worktree &&
+       GIT_WORK_TREE=../other_worktree git status 2>../err &&
+       echo "warning: Untracked cache is disabled on this system or location." >../expect &&
+       test_cmp ../expect ../err
+'
+
 test_done
index 1eef93c2b292c8ec649f12c826587365e5a0d0e6..afe36a533c4bc603d5acced8de1d607a4a7d5fc8 100755 (executable)
@@ -63,7 +63,7 @@ test_expect_success '"mixed" reset is not allowed in bare' '
 
 test_expect_success '"soft" reset is allowed in bare' '
        git reset --soft HEAD^ &&
-       test "`git show --pretty=format:%s | head -n 1`" = "one"
+       test "$(git show --pretty=format:%s | head -n 1)" = "one"
 '
 
 test_done
index dda3929d99aea3ea30d30b5715532fe6184d5259..68ea31d6936cd1b19efc812cd11f63b7a6ca4fbb 100755 (executable)
@@ -14,8 +14,8 @@ submodule and "git submodule update --rebase/--merge" does not detach the HEAD.
 
 compare_head()
 {
-    sha_master=`git rev-list --max-count=1 master`
-    sha_head=`git rev-list --max-count=1 HEAD`
+    sha_master=$(git rev-list --max-count=1 master)
+    sha_head=$(git rev-list --max-count=1 HEAD)
 
     test "$sha_master" = "$sha_head"
 }
index b770b2f04d56336f92b9394b4a2ce22a241480c4..eaea19b8f291ef6b9f13a05342dc10317f3bfbe9 100755 (executable)
@@ -6,7 +6,7 @@
 test_description='test clone --reference'
 . ./test-lib.sh
 
-base_dir=`pwd`
+base_dir=$(pwd)
 
 U=$base_dir/UPLOAD_LOG
 
index 1f53ea8090355c9a351da1983388e1a49fd88ae3..8728db61d38905d9e3e699cb9f450716e4236017 100755 (executable)
@@ -179,7 +179,7 @@ EOF
 chmod +x "$HOOK"
 
 commit_msg_is () {
-       test "`git log --pretty=format:%s%b -1`" = "$1"
+       test "$(git log --pretty=format:%s%b -1)" = "$1"
 }
 
 test_expect_success 'hook edits commit message' '
index 03dce09cfea5f1b5c19e7e8c4537a657cdf55dfc..b13f72975ecce17887c4c8275c6935d78d4b09a0 100755 (executable)
@@ -53,7 +53,7 @@ test_expect_success 'with hook (-m)' '
        echo "more" >> file &&
        git add file &&
        git commit -m "more" &&
-       test "`git log -1 --pretty=format:%s`" = "message (no editor)"
+       test "$(git log -1 --pretty=format:%s)" = "message (no editor)"
 
 '
 
@@ -62,7 +62,7 @@ test_expect_success 'with hook (-m editor)' '
        echo "more" >> file &&
        git add file &&
        GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -m "more more" &&
-       test "`git log -1 --pretty=format:%s`" = message
+       test "$(git log -1 --pretty=format:%s)" = message
 
 '
 
@@ -71,7 +71,7 @@ test_expect_success 'with hook (-t)' '
        echo "more" >> file &&
        git add file &&
        git commit -t "$(git rev-parse --git-dir)/template" &&
-       test "`git log -1 --pretty=format:%s`" = template
+       test "$(git log -1 --pretty=format:%s)" = template
 
 '
 
@@ -80,7 +80,7 @@ test_expect_success 'with hook (-F)' '
        echo "more" >> file &&
        git add file &&
        (echo more | git commit -F -) &&
-       test "`git log -1 --pretty=format:%s`" = "message (no editor)"
+       test "$(git log -1 --pretty=format:%s)" = "message (no editor)"
 
 '
 
@@ -89,17 +89,17 @@ test_expect_success 'with hook (-F editor)' '
        echo "more" >> file &&
        git add file &&
        (echo more more | GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -e -F -) &&
-       test "`git log -1 --pretty=format:%s`" = message
+       test "$(git log -1 --pretty=format:%s)" = message
 
 '
 
 test_expect_success 'with hook (-C)' '
 
-       head=`git rev-parse HEAD` &&
+       head=$(git rev-parse HEAD) &&
        echo "more" >> file &&
        git add file &&
        git commit -C $head &&
-       test "`git log -1 --pretty=format:%s`" = "$head (no editor)"
+       test "$(git log -1 --pretty=format:%s)" = "$head (no editor)"
 
 '
 
@@ -108,27 +108,27 @@ test_expect_success 'with hook (editor)' '
        echo "more more" >> file &&
        git add file &&
        GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit &&
-       test "`git log -1 --pretty=format:%s`" = default
+       test "$(git log -1 --pretty=format:%s)" = default
 
 '
 
 test_expect_success 'with hook (--amend)' '
 
-       head=`git rev-parse HEAD` &&
+       head=$(git rev-parse HEAD) &&
        echo "more" >> file &&
        git add file &&
        GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --amend &&
-       test "`git log -1 --pretty=format:%s`" = "$head"
+       test "$(git log -1 --pretty=format:%s)" = "$head"
 
 '
 
 test_expect_success 'with hook (-c)' '
 
-       head=`git rev-parse HEAD` &&
+       head=$(git rev-parse HEAD) &&
        echo "more" >> file &&
        git add file &&
        GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head &&
-       test "`git log -1 --pretty=format:%s`" = "$head"
+       test "$(git log -1 --pretty=format:%s)" = "$head"
 
 '
 
@@ -141,7 +141,7 @@ test_expect_success 'with hook (merge)' '
        git commit -m other &&
        git checkout - &&
        git merge --no-ff other &&
-       test "`git log -1 --pretty=format:%s`" = "merge (no editor)"
+       test "$(git log -1 --pretty=format:%s)" = "merge (no editor)"
 '
 
 test_expect_success 'with hook and editor (merge)' '
@@ -153,7 +153,7 @@ test_expect_success 'with hook and editor (merge)' '
        git commit -m other &&
        git checkout - &&
        env GIT_EDITOR="\"\$FAKE_EDITOR\"" git merge --no-ff -e other &&
-       test "`git log -1 --pretty=format:%s`" = "merge"
+       test "$(git log -1 --pretty=format:%s)" = "merge"
 '
 
 cat > "$HOOK" <<'EOF'
@@ -164,7 +164,7 @@ EOF
 test_expect_success 'with failing hook' '
 
        test_when_finished "git checkout -f master" &&
-       head=`git rev-parse HEAD` &&
+       head=$(git rev-parse HEAD) &&
        echo "more" >> file &&
        git add file &&
        test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit -c $head
@@ -174,7 +174,7 @@ test_expect_success 'with failing hook' '
 test_expect_success 'with failing hook (--no-verify)' '
 
        test_when_finished "git checkout -f master" &&
-       head=`git rev-parse HEAD` &&
+       head=$(git rev-parse HEAD) &&
        echo "more" >> file &&
        git add file &&
        test_must_fail env GIT_EDITOR="\"\$FAKE_EDITOR\"" git commit --no-verify -c $head
index 322c436a494c14a7350d6fdd85efbfbc5a7a8d28..aee785cffa8d656fa52e6b893921153faf748fe9 100755 (executable)
@@ -326,6 +326,46 @@ test_expect_success 'with complex patch, args and --trim-empty' '
        test_cmp expected actual
 '
 
+test_expect_success 'in-place editing with basic patch' '
+       cat basic_message >message &&
+       cat basic_patch >>message &&
+       cat basic_message >expected &&
+       echo >>expected &&
+       cat basic_patch >>expected &&
+       git interpret-trailers --in-place message &&
+       test_cmp expected message
+'
+
+test_expect_success 'in-place editing with additional trailer' '
+       cat basic_message >message &&
+       cat basic_patch >>message &&
+       cat basic_message >expected &&
+       echo >>expected &&
+       cat >>expected <<-\EOF &&
+               Reviewed-by: Alice
+       EOF
+       cat basic_patch >>expected &&
+       git interpret-trailers --trailer "Reviewed-by: Alice" --in-place message &&
+       test_cmp expected message
+'
+
+test_expect_success 'in-place editing on stdin disallowed' '
+       test_must_fail git interpret-trailers --trailer "Reviewed-by: Alice" --in-place < basic_message
+'
+
+test_expect_success 'in-place editing on non-existing file' '
+       test_must_fail git interpret-trailers --trailer "Reviewed-by: Alice" --in-place nonexisting &&
+       test_path_is_missing nonexisting
+'
+
+test_expect_success POSIXPERM,SANITY "in-place editing doesn't clobber original file on error" '
+       cat basic_message >message &&
+       chmod -r message &&
+       test_must_fail git interpret-trailers --trailer "Reviewed-by: Alice" --in-place message &&
+       chmod +r message &&
+       test_cmp message basic_message
+'
+
 test_expect_success 'using "where = before"' '
        git config trailer.bug.where "before" &&
        cat complex_message_body >expected &&
index 955f09f8e818cea8d32e453cd4971ff362d69bea..6abe441ae3611906143a76ac2b4acca7ab5ff671 100755 (executable)
@@ -19,7 +19,7 @@ test_expect_success 'setup' '
                git add c$i.c &&
                git commit -m c$i &&
                git tag c$i &&
-               i=`expr $i + 1` || return 1
+               i=$(expr $i + 1) || return 1
        done
 '
 
@@ -30,7 +30,7 @@ test_expect_success 'merge c1 with c2, c3, c4, ... c29' '
        while test $i -le 30
        do
                refs="$refs c$i"
-               i=`expr $i + 1`
+               i=$(expr $i + 1)
        done &&
        git merge $refs &&
        test "$(git rev-parse c1)" != "$(git rev-parse HEAD)" &&
@@ -38,14 +38,14 @@ test_expect_success 'merge c1 with c2, c3, c4, ... c29' '
        while test $i -le 30
        do
                test "$(git rev-parse c$i)" = "$(git rev-parse HEAD^$i)" &&
-               i=`expr $i + 1` || return 1
+               i=$(expr $i + 1) || return 1
        done &&
        git diff --exit-code &&
        i=1 &&
        while test $i -le 30
        do
                test -f c$i.c &&
-               i=`expr $i + 1` || return 1
+               i=$(expr $i + 1) || return 1
        done
 '
 
index 021c5479bdf4665e815590dc05a0831e7d92c53c..6061a04147a06dba0d049cbb5d31f8049c2210d0 100755 (executable)
@@ -69,7 +69,7 @@ test_expect_success 'writing bitmaps via config can duplicate .keep objects' '
 
 test_expect_success 'loose objects in alternate ODB are not repacked' '
        mkdir alt_objects &&
-       echo `pwd`/alt_objects > .git/objects/info/alternates &&
+       echo $(pwd)/alt_objects > .git/objects/info/alternates &&
        echo content3 > file3 &&
        objsha1=$(GIT_OBJECT_DIRECTORY=alt_objects git hash-object -w file3) &&
        git add file3 &&
@@ -168,7 +168,7 @@ test_expect_success 'packed unreachable obs in alternate ODB are not loosened' '
 '
 
 test_expect_success 'local packed unreachable obs that exist in alternate ODB are not loosened' '
-       echo `pwd`/alt_objects > .git/objects/info/alternates &&
+       echo $(pwd)/alt_objects > .git/objects/info/alternates &&
        echo "$csha1" | git pack-objects --non-empty --all --reflog pack &&
        rm -f .git/objects/pack/* &&
        mv pack-* .git/objects/pack/ &&
index 028ffe4a05c066c112655822a351b64ed80f9c99..b540944408a6feb35f28ff7e18601db7a29f8635 100755 (executable)
@@ -791,12 +791,12 @@ test_expect_success 'outside of git repository' '
        } >non/expect.full &&
        echo file2:world >non/expect.sub &&
        (
-               GIT_CEILING_DIRECTORIES="$(pwd)/non/git" &&
+               GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
                export GIT_CEILING_DIRECTORIES &&
                cd non/git &&
                test_must_fail git grep o &&
                git grep --no-index o >../actual.full &&
-               test_cmp ../expect.full ../actual.full
+               test_cmp ../expect.full ../actual.full &&
                cd sub &&
                test_must_fail git grep o &&
                git grep --no-index o >../../actual.sub &&
@@ -805,7 +805,7 @@ test_expect_success 'outside of git repository' '
 
        echo ".*o*" >non/git/.gitignore &&
        (
-               GIT_CEILING_DIRECTORIES="$(pwd)/non/git" &&
+               GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
                export GIT_CEILING_DIRECTORIES &&
                cd non/git &&
                test_must_fail git grep o &&
@@ -813,7 +813,7 @@ test_expect_success 'outside of git repository' '
                test_cmp ../expect.full ../actual.full &&
 
                {
-                       echo ".gitignore:.*o*"
+                       echo ".gitignore:.*o*" &&
                        cat ../expect.full
                } >../expect.with.ignored &&
                git grep --no-index --no-exclude o >../actual.full &&
@@ -821,6 +821,47 @@ test_expect_success 'outside of git repository' '
        )
 '
 
+test_expect_success 'outside of git repository with fallbackToNoIndex' '
+       rm -fr non &&
+       mkdir -p non/git/sub &&
+       echo hello >non/git/file1 &&
+       echo world >non/git/sub/file2 &&
+       cat <<-\EOF >non/expect.full &&
+       file1:hello
+       sub/file2:world
+       EOF
+       echo file2:world >non/expect.sub &&
+       (
+               GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
+               export GIT_CEILING_DIRECTORIES &&
+               cd non/git &&
+               test_must_fail git -c grep.fallbackToNoIndex=false grep o &&
+               git -c grep.fallbackToNoIndex=true grep o >../actual.full &&
+               test_cmp ../expect.full ../actual.full &&
+               cd sub &&
+               test_must_fail git -c grep.fallbackToNoIndex=false grep o &&
+               git -c grep.fallbackToNoIndex=true grep o >../../actual.sub &&
+               test_cmp ../../expect.sub ../../actual.sub
+       ) &&
+
+       echo ".*o*" >non/git/.gitignore &&
+       (
+               GIT_CEILING_DIRECTORIES="$(pwd)/non" &&
+               export GIT_CEILING_DIRECTORIES &&
+               cd non/git &&
+               test_must_fail git -c grep.fallbackToNoIndex=false grep o &&
+               git -c grep.fallbackToNoIndex=true grep --exclude-standard o >../actual.full &&
+               test_cmp ../expect.full ../actual.full &&
+
+               {
+                       echo ".gitignore:.*o*" &&
+                       cat ../expect.full
+               } >../expect.with.ignored &&
+               git -c grep.fallbackToNoIndex grep --no-exclude o >../actual.full &&
+               test_cmp ../expect.with.ignored ../actual.full
+       )
+'
+
 test_expect_success 'inside git repository but with --no-index' '
        rm -fr is &&
        mkdir -p is/git/sub &&
index 16f1442c1e6e4780dc10474a3fbf516841468c9f..6568429753d5f90426ad6acc0703b79e9f7a3284 100755 (executable)
@@ -153,7 +153,7 @@ test_expect_success 'blame path that used to be a directory' '
 '
 
 test_expect_success 'blame to a commit with no author name' '
-  TREE=`git rev-parse HEAD:` &&
+  TREE=$(git rev-parse HEAD:) &&
   cat >badcommit <<EOF &&
 tree $TREE
 author <noname> 1234567890 +0000
@@ -161,7 +161,7 @@ committer David Reiss <dreiss@facebook.com> 1234567890 +0000
 
 some message
 EOF
-  COMMIT=`git hash-object -t commit -w badcommit` &&
+  COMMIT=$(git hash-object -t commit -w badcommit) &&
   git --no-pager blame $COMMIT -- uno >/dev/null
 '
 
index 3c49536e0e8d2ae0e046b498ad6efaccab8e9f1b..b3355d2c7016e55e99a465414f230569c3807230 100755 (executable)
@@ -36,7 +36,7 @@ clean_fake_sendmail () {
 }
 
 test_expect_success $PREREQ 'Extract patches' '
-       patches=`git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1`
+       patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1)
 '
 
 # Test no confirm early to ensure remaining tests will not hang
@@ -1151,7 +1151,7 @@ test_expect_success $PREREQ '--no-bcc overrides sendemail.bcc' '
 '
 
 test_expect_success $PREREQ 'patches To headers are used by default' '
-       patch=`git format-patch -1 --to="bodies@example.com"` &&
+       patch=$(git format-patch -1 --to="bodies@example.com") &&
        test_when_finished "rm $patch" &&
        git send-email \
                --dry-run \
@@ -1162,7 +1162,7 @@ test_expect_success $PREREQ 'patches To headers are used by default' '
 '
 
 test_expect_success $PREREQ 'patches To headers are appended to' '
-       patch=`git format-patch -1 --to="bodies@example.com"` &&
+       patch=$(git format-patch -1 --to="bodies@example.com") &&
        test_when_finished "rm $patch" &&
        git send-email \
                --dry-run \
@@ -1175,8 +1175,8 @@ test_expect_success $PREREQ 'patches To headers are appended to' '
 '
 
 test_expect_success $PREREQ 'To headers from files reset each patch' '
-       patch1=`git format-patch -1 --to="bodies@example.com"` &&
-       patch2=`git format-patch -1 --to="other@example.com" HEAD~` &&
+       patch1=$(git format-patch -1 --to="bodies@example.com") &&
+       patch2=$(git format-patch -1 --to="other@example.com" HEAD~) &&
        test_when_finished "rm $patch1 && rm $patch2" &&
        git send-email \
                --dry-run \
@@ -1488,7 +1488,7 @@ test_cover_addresses () {
        clean_fake_sendmail &&
        rm -fr outdir &&
        git format-patch --cover-letter -2 -o outdir &&
-       cover=`echo outdir/0000-*.patch` &&
+       cover=$(echo outdir/0000-*.patch) &&
        mv $cover cover-to-edit.patch &&
        perl -pe "s/^From:/$header: extra\@address.com\nFrom:/" cover-to-edit.patch >"$cover" &&
        git send-email \
@@ -1527,6 +1527,21 @@ test_expect_success $PREREQ 'cccover adds Cc to all mail' '
        test_cover_addresses "Cc"
 '
 
+test_expect_success $PREREQ 'escaped quotes in sendemail.aliasfiletype=mutt' '
+       clean_fake_sendmail &&
+       echo "alias sbd \\\"Dot U. Sir\\\" <somebody@example.org>" >.mutt &&
+       git config --replace-all sendemail.aliasesfile "$(pwd)/.mutt" &&
+       git config sendemail.aliasfiletype mutt &&
+       git send-email \
+               --from="Example <nobody@example.com>" \
+               --to=sbd \
+               --smtp-server="$(pwd)/fake.sendmail" \
+               outdir/0001-*.patch \
+               2>errors >out &&
+       grep "^!somebody@example\.org!$" commandline1 &&
+       grep -F "To: \"Dot U. Sir\" <somebody@example.org>" out
+'
+
 test_expect_success $PREREQ 'sendemail.aliasfiletype=mailrc' '
        clean_fake_sendmail &&
        echo "alias sbd  somebody@example.org" >.mailrc &&
index 4fea8d901bbc0f713a1500adbbdd2e5886720f47..258d9b8cefb6bbf81a64098d57db03f7c1da90c6 100755 (executable)
@@ -265,18 +265,18 @@ test_expect_success 'able to dcommit to a subdirectory' "
        git update-index --add d &&
        git commit -m '/bar/d should be in the log' &&
        git svn dcommit -i bar &&
-       test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" &&
+       test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" &&
        mkdir newdir &&
        echo new > newdir/dir &&
        git update-index --add newdir/dir &&
        git commit -m 'add a new directory' &&
        git svn dcommit -i bar &&
-       test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" &&
+       test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" &&
        echo foo >> newdir/dir &&
        git update-index newdir/dir &&
        git commit -m 'modify a file in new directory' &&
        git svn dcommit -i bar &&
-       test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
+       test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\"
        "
 
 test_expect_success 'dcommit should not fail with a touched file' '
@@ -295,7 +295,7 @@ test_expect_success 'able to set-tree to a subdirectory' "
        git update-index d &&
        git commit -m 'update /bar/d' &&
        git svn set-tree -i bar HEAD &&
-       test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\"
+       test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\"
        "
 
 test_expect_success 'git-svn works in a bare repository' '
index 8869f5018ecd06636dc3e722cb518af88a6919d9..e8173d5fefa205fe74aae88a1e32247a71340bfb 100755 (executable)
@@ -26,27 +26,27 @@ cd import
 EOF
 
        printf "Hello\r\nWorld\r\n" > crlf
-       a_crlf=`git hash-object -w crlf`
+       a_crlf=$(git hash-object -w crlf)
        printf "Hello\rWorld\r" > cr
-       a_cr=`git hash-object -w cr`
+       a_cr=$(git hash-object -w cr)
        printf "Hello\nWorld\n" > lf
-       a_lf=`git hash-object -w lf`
+       a_lf=$(git hash-object -w lf)
 
        printf "Hello\r\nWorld" > ne_crlf
-       a_ne_crlf=`git hash-object -w ne_crlf`
+       a_ne_crlf=$(git hash-object -w ne_crlf)
        printf "Hello\nWorld" > ne_lf
-       a_ne_lf=`git hash-object -w ne_lf`
+       a_ne_lf=$(git hash-object -w ne_lf)
        printf "Hello\rWorld" > ne_cr
-       a_ne_cr=`git hash-object -w ne_cr`
+       a_ne_cr=$(git hash-object -w ne_cr)
 
        touch empty
-       a_empty=`git hash-object -w empty`
+       a_empty=$(git hash-object -w empty)
        printf "\n" > empty_lf
-       a_empty_lf=`git hash-object -w empty_lf`
+       a_empty_lf=$(git hash-object -w empty_lf)
        printf "\r" > empty_cr
-       a_empty_cr=`git hash-object -w empty_cr`
+       a_empty_cr=$(git hash-object -w empty_cr)
        printf "\r\n" > empty_crlf
-       a_empty_crlf=`git hash-object -w empty_crlf`
+       a_empty_crlf=$(git hash-object -w empty_crlf)
 
        svn_cmd import --no-auto-props -m 'import for git svn' . "$svnrepo" >/dev/null
 cd ..
@@ -80,7 +80,7 @@ test_expect_success "$name" \
        git pull . ${remotes_git_svn}'
 
 expect='/* $Id$ */'
-got="`sed -ne 2p kw.c`"
+got="$(sed -ne 2p kw.c)"
 test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'"
 
 test_expect_success "propset CR on crlf files" '
@@ -107,8 +107,8 @@ done
 cd test_wc
        printf '$Id$\rHello\rWorld\r' > cr
        printf '$Id$\rHello\rWorld' > ne_cr
-       a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin`
-       a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin`
+       a_cr=$(printf '$Id$\r\nHello\r\nWorld\r\n' | git hash-object --stdin)
+       a_ne_cr=$(printf '$Id$\r\nHello\r\nWorld' | git hash-object --stdin)
        test_expect_success 'Set CRLF on cr files' \
        'svn_cmd propset svn:eol-style CRLF cr &&
         svn_cmd propset svn:eol-style CRLF ne_cr &&
@@ -119,8 +119,8 @@ cd ..
 test_expect_success 'fetch and pull latest from svn' \
        'git svn fetch && git pull . ${remotes_git_svn}'
 
-b_cr="`git hash-object cr`"
-b_ne_cr="`git hash-object ne_cr`"
+b_cr="$(git hash-object cr)"
+b_ne_cr="$(git hash-object ne_cr)"
 
 test_expect_success 'CRLF + $Id$' "test '$a_cr' = '$b_cr'"
 test_expect_success 'CRLF + $Id$ (no newline)' "test '$a_ne_cr' = '$b_ne_cr'"
index 83f17e13e805300f03016e8fc66c717db2657f3c..cd480edf1606fda8d973ee3decb8e18e03356153 100755 (executable)
@@ -31,12 +31,12 @@ test_expect_success 'initialize repo' '
 test_expect_success 'init and fetch a moved directory' '
        git svn init --minimize-url -i thunk "$svnrepo"/thunk &&
        git svn fetch -i thunk &&
-       test "`git rev-parse --verify refs/remotes/thunk@2`" \
-           = "`git rev-parse --verify refs/remotes/thunk~1`" &&
-        test "`git cat-file blob refs/remotes/thunk:readme |\
-                 sed -n -e "3p"`" = goodbye &&
-       test -z "`git config --get svn-remote.svn.fetch \
-                "^trunk:refs/remotes/thunk@2$"`"
+       test "$(git rev-parse --verify refs/remotes/thunk@2)" \
+          = "$(git rev-parse --verify refs/remotes/thunk~1)" &&
+       test "$(git cat-file blob refs/remotes/thunk:readme |\
+                sed -n -e "3p")" = goodbye &&
+       test -z "$(git config --get svn-remote.svn.fetch \
+                "^trunk:refs/remotes/thunk@2$")"
        '
 
 test_expect_success 'init and fetch from one svn-remote' '
@@ -46,10 +46,10 @@ test_expect_success 'init and fetch from one svn-remote' '
         git config --add svn-remote.svn.fetch \
           thunk:refs/remotes/svn/thunk &&
         git svn fetch -i svn/thunk &&
-       test "`git rev-parse --verify refs/remotes/svn/trunk`" \
-           = "`git rev-parse --verify refs/remotes/svn/thunk~1`" &&
-        test "`git cat-file blob refs/remotes/svn/thunk:readme |\
-                 sed -n -e "3p"`" = goodbye
+       test "$(git rev-parse --verify refs/remotes/svn/trunk)" \
+          = "$(git rev-parse --verify refs/remotes/svn/thunk~1)" &&
+       test "$(git cat-file blob refs/remotes/svn/thunk:readme |\
+                sed -n -e "3p")" = goodbye
         '
 
 test_expect_success 'follow deleted parent' '
@@ -61,9 +61,9 @@ test_expect_success 'follow deleted parent' '
           junk:refs/remotes/svn/junk &&
         git svn fetch -i svn/thunk &&
         git svn fetch -i svn/junk &&
-        test -z "`git diff svn/junk svn/trunk`" &&
-        test "`git merge-base svn/junk svn/trunk`" \
-           = "`git rev-parse svn/trunk`"
+       test -z "$(git diff svn/junk svn/trunk)" &&
+       test "$(git merge-base svn/junk svn/trunk)" \
+          = "$(git rev-parse svn/trunk)"
         '
 
 test_expect_success 'follow larger parent' '
@@ -80,10 +80,10 @@ test_expect_success 'follow larger parent' '
         git rev-parse --verify refs/remotes/larger &&
         git rev-parse --verify \
           refs/remotes/larger-parent &&
-        test "`git merge-base \
+       test "$(git merge-base \
                 refs/remotes/larger-parent \
-                 refs/remotes/larger`" = \
-             "`git rev-parse refs/remotes/larger`"
+                refs/remotes/larger)" = \
+            "$(git rev-parse refs/remotes/larger)"
         '
 
 test_expect_success 'follow higher-level parent' '
@@ -106,8 +106,8 @@ test_expect_success 'follow deleted directory' '
        svn_cmd rm -m "remove glob" "$svnrepo"/glob &&
        git svn init --minimize-url -i glob "$svnrepo"/glob &&
        git svn fetch -i glob &&
-       test "`git cat-file blob refs/remotes/glob:blob/bye`" = hi &&
-       test "`git ls-tree refs/remotes/glob | wc -l `" -eq 1
+       test "$(git cat-file blob refs/remotes/glob:blob/bye)" = hi &&
+       test "$(git ls-tree refs/remotes/glob | wc -l )" -eq 1
        '
 
 # ref: r9270 of the Subversion repository: (http://svn.collab.net/repos/svn)
@@ -142,9 +142,9 @@ test_expect_success 'follow-parent avoids deleting relevant info' '
        git svn init --minimize-url -i r9270-t \
          "$svnrepo"/r9270/trunk/subversion/bindings/swig/perl/native/t &&
        git svn fetch -i r9270-t &&
-       test `git rev-list r9270-t | wc -l` -eq 2 &&
-       test "`git ls-tree --name-only r9270-t~1`" = \
-            "`git ls-tree --name-only r9270-t`"
+       test $(git rev-list r9270-t | wc -l) -eq 2 &&
+       test "$(git ls-tree --name-only r9270-t~1)" = \
+            "$(git ls-tree --name-only r9270-t)"
        '
 
 test_expect_success "track initial change if it was only made to parent" '
@@ -152,11 +152,11 @@ test_expect_success "track initial change if it was only made to parent" '
        git svn init --minimize-url -i r9270-d \
          "$svnrepo"/r9270/drunk/subversion/bindings/swig/perl/native/t &&
        git svn fetch -i r9270-d &&
-       test `git rev-list r9270-d | wc -l` -eq 3 &&
-       test "`git ls-tree --name-only r9270-t`" = \
-            "`git ls-tree --name-only r9270-d`" &&
-       test "`git rev-parse r9270-t`" = \
-            "`git rev-parse r9270-d~1`"
+       test $(git rev-list r9270-d | wc -l) -eq 3 &&
+       test "$(git ls-tree --name-only r9270-t)" = \
+            "$(git ls-tree --name-only r9270-d)" &&
+       test "$(git rev-parse r9270-t)" = \
+            "$(git rev-parse r9270-d~1)"
        '
 
 test_expect_success "follow-parent is atomic" '
@@ -193,19 +193,19 @@ test_expect_success "follow-parent is atomic" '
        git svn fetch -i stunk &&
        git svn init --minimize-url -i flunked "$svnrepo"/flunked &&
        git svn fetch -i flunked &&
-       test "`git rev-parse --verify refs/remotes/flunk@18`" \
-          = "`git rev-parse --verify refs/remotes/stunk`" &&
-       test "`git rev-parse --verify refs/remotes/flunk~1`" \
-          = "`git rev-parse --verify refs/remotes/stunk`" &&
-       test "`git rev-parse --verify refs/remotes/flunked~1`" \
-          = "`git rev-parse --verify refs/remotes/stunk~1`"
+       test "$(git rev-parse --verify refs/remotes/flunk@18)" \
+          = "$(git rev-parse --verify refs/remotes/stunk)" &&
+       test "$(git rev-parse --verify refs/remotes/flunk~1)" \
+          = "$(git rev-parse --verify refs/remotes/stunk)" &&
+       test "$(git rev-parse --verify refs/remotes/flunked~1)" \
+          = "$(git rev-parse --verify refs/remotes/stunk~1)"
        '
 
 test_expect_success "track multi-parent paths" '
        svn_cmd cp -m "resurrect /glob" "$svnrepo"/r9270 "$svnrepo"/glob &&
        git svn multi-fetch &&
-       test `git cat-file commit refs/remotes/glob | \
-              grep "^parent " | wc -l` -eq 2
+       test $(git cat-file commit refs/remotes/glob | \
+              grep "^parent " | wc -l) -eq 2
        '
 
 test_expect_success "multi-fetch continues to work" "
index 5d0afeae6caf03ca34d7ef883baed512bcbcec51..6ed5f74e259ded8d7d336deaf22474aa504e060b 100755 (executable)
@@ -18,8 +18,8 @@ test_expect_success 'initialize repo' '
        git commit -a -m "another"
        '
 
-head=`git rev-parse --verify HEAD^0`
-prev=`git rev-parse --verify HEAD^1`
+head=$(git rev-parse --verify HEAD^0)
+prev=$(git rev-parse --verify HEAD^1)
 
 # the internals of the commit-diff command are the same as the regular
 # commit, so only a basic test of functionality is needed since we've
index 6e69fc4c65aeb77b1a4d784c7842762090ae6787..906019803797b01a4b447858d7766486bba951aa 100755 (executable)
@@ -24,10 +24,10 @@ test_expect_success 'setup old-looking metadata' '
        git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn}
        '
 
-head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
+head=$(git rev-parse --verify refs/heads/git-svn-HEAD^0)
 test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
 
-svnrepo_escaped=`echo $svnrepo | sed 's/ /%20/'`
+svnrepo_escaped=$(echo $svnrepo | sed 's/ /%20/')
 
 test_expect_success 'initialize old-style (v0) git svn layout' '
        mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
@@ -38,7 +38,7 @@ test_expect_success 'initialize old-style (v0) git svn layout' '
        git rev-parse --verify refs/${remotes_git_svn}^0 &&
        git rev-parse --verify refs/remotes/svn^0 &&
        test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" &&
-       test `git config --get svn-remote.svn.fetch` = \
+       test $(git config --get svn-remote.svn.fetch) = \
              ":refs/${remotes_git_svn}"
        '
 
@@ -46,10 +46,10 @@ test_expect_success 'initialize a multi-repository repo' '
        git svn init "$svnrepo" -T trunk -t tags -b branches &&
        git config --get-all svn-remote.svn.fetch > fetch.out &&
        grep "^trunk:refs/remotes/origin/trunk$" fetch.out &&
-       test -n "`git config --get svn-remote.svn.branches \
-                   "^branches/\*:refs/remotes/origin/\*$"`" &&
-       test -n "`git config --get svn-remote.svn.tags \
-                   "^tags/\*:refs/remotes/origin/tags/\*$"`" &&
+       test -n "$(git config --get svn-remote.svn.branches \
+                   "^branches/\*:refs/remotes/origin/\*$")" &&
+       test -n "$(git config --get svn-remote.svn.tags \
+                   "^tags/\*:refs/remotes/origin/tags/\*$")" &&
        git config --unset svn-remote.svn.branches \
                                "^branches/\*:refs/remotes/origin/\*$" &&
        git config --unset svn-remote.svn.tags \
@@ -75,28 +75,28 @@ test_expect_success 'multi-fetch works on partial urls + paths' "
        for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do
                git rev-parse --verify refs/remotes/origin/\$i^0 >> refs.out || exit 1;
            done &&
-       test -z \"\`sort < refs.out | uniq -d\`\" &&
+       test -z \"\$(sort < refs.out | uniq -d)\" &&
        for i in trunk a b tags/0.1 tags/0.2 tags/0.3; do
          for j in trunk a b tags/0.1 tags/0.2 tags/0.3; do
                if test \$j != \$i; then continue; fi
-           test -z \"\`git diff refs/remotes/origin/\$i \
-                                refs/remotes/origin/\$j\`\" ||exit 1; done; done
+           test -z \"\$(git diff refs/remotes/origin/\$i \
+                                refs/remotes/origin/\$j)\" ||exit 1; done; done
        "
 
 test_expect_success 'migrate --minimize on old inited layout' '
        git config --unset-all svn-remote.svn.fetch &&
        git config --unset-all svn-remote.svn.url &&
        rm -rf "$GIT_DIR"/svn &&
-       for i in `cat fetch.out`; do
-               path=`expr $i : "\([^:]*\):.*$"`
-               ref=`expr $i : "[^:]*:\(refs/remotes/.*\)$"`
+       for i in $(cat fetch.out); do
+               path=$(expr $i : "\([^:]*\):.*$")
+               ref=$(expr $i : "[^:]*:\(refs/remotes/.*\)$")
                if test -z "$ref"; then continue; fi
                if test -n "$path"; then path="/$path"; fi
                ( mkdir -p "$GIT_DIR"/svn/$ref/info/ &&
                echo "$svnrepo"$path > "$GIT_DIR"/svn/$ref/info/url ) || exit 1;
        done &&
        git svn migrate --minimize &&
-       test -z "`git config -l | grep "^svn-remote\.git-svn\."`" &&
+       test -z "$(git config -l | grep "^svn-remote\.git-svn\.")" &&
        git config --get-all svn-remote.svn.fetch > fetch.out &&
        grep "^trunk:refs/remotes/origin/trunk$" fetch.out &&
        grep "^branches/a:refs/remotes/origin/a$" fetch.out &&
index d732d3130299e964359784949fc97805a2888e39..a526d603793957f781002c98b2da60e1005bf39f 100755 (executable)
@@ -50,10 +50,10 @@ test_expect_success 'test refspec globbing' '
        git log --pretty=oneline refs/remotes/tags/end | \
            sed -e "s/^.\{41\}//" > output.end &&
        test_cmp expect.end output.end &&
-       test "`git rev-parse refs/remotes/tags/end~1`" = \
-               "`git rev-parse refs/remotes/branches/start`" &&
-       test "`git rev-parse refs/remotes/branches/start~2`" = \
-               "`git rev-parse refs/remotes/trunk`" &&
+       test "$(git rev-parse refs/remotes/tags/end~1)" = \
+               "$(git rev-parse refs/remotes/branches/start)" &&
+       test "$(git rev-parse refs/remotes/branches/start~2)" = \
+               "$(git rev-parse refs/remotes/trunk)" &&
        test_must_fail git rev-parse refs/remotes/tags/end@3
        '
 
@@ -75,12 +75,12 @@ test_expect_success 'test left-hand-side only globbing' '
                svn_cmd commit -m "try to try"
        ) &&
        git svn fetch two &&
-       test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
-       test `git rev-list refs/remotes/two/branches/start | wc -l` -eq 3 &&
-       test `git rev-parse refs/remotes/two/branches/start~2` = \
-            `git rev-parse refs/remotes/two/trunk` &&
-       test `git rev-parse refs/remotes/two/tags/end~3` = \
-            `git rev-parse refs/remotes/two/branches/start` &&
+       test $(git rev-list refs/remotes/two/tags/end | wc -l) -eq 6 &&
+       test $(git rev-list refs/remotes/two/branches/start | wc -l) -eq 3 &&
+       test $(git rev-parse refs/remotes/two/branches/start~2) = \
+            $(git rev-parse refs/remotes/two/trunk) &&
+       test $(git rev-parse refs/remotes/two/tags/end~3) = \
+            $(git rev-parse refs/remotes/two/branches/start) &&
        git log --pretty=oneline refs/remotes/two/tags/end | \
            sed -e "s/^.\{41\}//" > output.two &&
        test_cmp expect.two output.two
index c318f9f946a35f0d13b90f67dd00a6817d77d989..f36b74924236ff54bc6400ff8afacdf95def363d 100755 (executable)
@@ -50,10 +50,10 @@ test_expect_success 'test refspec globbing' '
        git log --pretty=oneline refs/remotes/tags/end | \
            sed -e "s/^.\{41\}//" > output.end &&
        test_cmp expect.end output.end &&
-       test "`git rev-parse refs/remotes/tags/end~1`" = \
-               "`git rev-parse refs/remotes/branches/v1/start`" &&
-       test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
-               "`git rev-parse refs/remotes/trunk`" &&
+       test "$(git rev-parse refs/remotes/tags/end~1)" = \
+               "$(git rev-parse refs/remotes/branches/v1/start)" &&
+       test "$(git rev-parse refs/remotes/branches/v1/start~2)" = \
+               "$(git rev-parse refs/remotes/trunk)" &&
        test_must_fail git rev-parse refs/remotes/tags/end@3
        '
 
@@ -75,12 +75,12 @@ test_expect_success 'test left-hand-side only globbing' '
                svn_cmd commit -m "try to try"
        ) &&
        git svn fetch two &&
-       test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
-       test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
-       test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
-            `git rev-parse refs/remotes/two/trunk` &&
-       test `git rev-parse refs/remotes/two/tags/end~3` = \
-            `git rev-parse refs/remotes/two/branches/v1/start` &&
+       test $(git rev-list refs/remotes/two/tags/end | wc -l) -eq 6 &&
+       test $(git rev-list refs/remotes/two/branches/v1/start | wc -l) -eq 3 &&
+       test $(git rev-parse refs/remotes/two/branches/v1/start~2) = \
+            $(git rev-parse refs/remotes/two/trunk) &&
+       test $(git rev-parse refs/remotes/two/tags/end~3) = \
+            $(git rev-parse refs/remotes/two/branches/v1/start) &&
        git log --pretty=oneline refs/remotes/two/tags/end | \
            sed -e "s/^.\{41\}//" > output.two &&
        test_cmp expect.two output.two
@@ -124,12 +124,12 @@ test_expect_success 'test another branch' '
        git config --add svn-remote.four.tags \
                         "tags/*:refs/remotes/four/tags/*" &&
        git svn fetch four &&
-       test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
-       test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
-       test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
-            `git rev-parse refs/remotes/four/trunk` &&
-       test `git rev-parse refs/remotes/four/tags/next~2` = \
-            `git rev-parse refs/remotes/four/branches/v2/start` &&
+       test $(git rev-list refs/remotes/four/tags/next | wc -l) -eq 5 &&
+       test $(git rev-list refs/remotes/four/branches/v2/start | wc -l) -eq 3 &&
+       test $(git rev-parse refs/remotes/four/branches/v2/start~2) = \
+            $(git rev-parse refs/remotes/four/trunk) &&
+       test $(git rev-parse refs/remotes/four/tags/next~2) = \
+            $(git rev-parse refs/remotes/four/branches/v2/start) &&
        git log --pretty=oneline refs/remotes/four/tags/next | \
            sed -e "s/^.\{41\}//" > output.four &&
        test_cmp expect.four output.four
index a06e4c5b8e3fa5d5c0c14afede47c630ccb07712..29fbdfdd3f02c2dfb6219e749dadd8a495a6c97d 100755 (executable)
@@ -51,7 +51,7 @@ test_expect_success 'verify metadata for /dir' "
 
 test_expect_success 'find commit based on SVN revision number' "
         git svn find-rev r12 |
-           grep `git rev-parse HEAD`
+           grep $(git rev-parse HEAD)
         "
 
 test_expect_success 'empty rebase' "
index fb41876677a9025f2d267ade0c8898e63022a704..a3d388228a19cec73c7c9521905b82cd36d07752 100755 (executable)
@@ -68,8 +68,8 @@ test_expect_success 'setup git mirror and merge' '
 test_debug 'gitk --all & sleep 1'
 
 test_expect_success 'verify pre-merge ancestry' "
-       test x\`git rev-parse --verify refs/heads/svn^2\` = \
-            x\`git rev-parse --verify refs/heads/merge\` &&
+       test x\$(git rev-parse --verify refs/heads/svn^2) = \
+            x\$(git rev-parse --verify refs/heads/merge) &&
        git cat-file commit refs/heads/svn^ | grep '^friend$'
        "
 
@@ -80,10 +80,10 @@ test_expect_success 'git svn dcommit merges' "
 test_debug 'gitk --all & sleep 1'
 
 test_expect_success 'verify post-merge ancestry' "
-       test x\`git rev-parse --verify refs/heads/svn\` = \
-            x\`git rev-parse --verify refs/remotes/origin/trunk \` &&
-       test x\`git rev-parse --verify refs/heads/svn^2\` = \
-            x\`git rev-parse --verify refs/heads/merge\` &&
+       test x\$(git rev-parse --verify refs/heads/svn) = \
+            x\$(git rev-parse --verify refs/remotes/origin/trunk) &&
+       test x\$(git rev-parse --verify refs/heads/svn^2) = \
+            x\$(git rev-parse --verify refs/heads/merge) &&
        git cat-file commit refs/heads/svn^ | grep '^friend$'
        "
 
index ed4d1369cca6a232cdb7ed98fc75b074a808e46e..a2219154b89393effa51f87b3be56706728b6572 100755 (executable)
@@ -35,7 +35,7 @@ test_expect_success 'setup svnrepo' '
 # SVN 1.7 will truncate "not-a%40{0]" to just "not-a".
 # Look at what SVN wound up naming the branch and use that.
 # Be sure to escape the @ if it shows up.
-non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'`
+non_reflog=$(svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/')
 
 test_expect_success 'test clone with funky branch names' '
        git svn clone -s "$svnrepo/pr ject" project &&
index f16f3234a1acb9953ba33578b6cb689e2583ea80..88241baee32478c7ead525dece88f1e7c6edfa06 100755 (executable)
@@ -8,7 +8,7 @@ test_description='git svn info'
 
 # Tested with: svn, version 1.4.4 (r25188)
 # Tested with: svn, version 1.6.[12345689]
-v=`svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p'`
+v=$(svn_cmd --version | sed -n -e 's/^svn, version \(1\.[0-9]*\.[0-9]*\).*$/\1/p')
 case $v in
 1.[456].*)
        ;;
index 8cfdfe790f1e0bb7cd0ddb72a72a55073368ec60..39b6bcb398fff970184e242bdd51500b84f7d382 100755 (executable)
@@ -7,7 +7,7 @@ test_description='git svn honors i18n.commitEncoding in config'
 . ./lib-git-svn.sh
 
 compare_git_head_with () {
-       nr=`wc -l < "$1"`
+       nr=$(wc -l < "$1")
        a=7
        b=$(($a + $nr - 1))
        git cat-file commit HEAD | sed -ne "$a,${b}p" >current &&
@@ -29,7 +29,7 @@ fi
 compare_svn_head_with () {
        # extract just the log message and strip out committer info.
        # don't use --limit here since svn 1.1.x doesn't have it,
-       LC_ALL="$a_utf8_locale" svn log `git svn info --url` | perl -w -e '
+       LC_ALL="$a_utf8_locale" svn log $(git svn info --url) | perl -w -e '
                use bytes;
                $/ = ("-"x72) . "\n";
                my @x = <STDIN>;
index c44de267a1c0e2546eb06c3607d2daef41a6a330..d306b77c31e6a73cc777b71eba1f69090093c0dc 100755 (executable)
@@ -26,7 +26,7 @@ test_expect_success 'start import with incomplete authors file' '
 test_expect_success 'imported 2 revisions successfully' '
        (
                cd x
-               test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 &&
+               test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 2 &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn | \
                  grep "^author BBBBBBB BBBBBBB <bb@example\.com> " &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
@@ -43,7 +43,7 @@ test_expect_success 'continues to import once authors have been added' '
        (
                cd x
                git svn fetch --authors-file=../svn-authors &&
-               test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 &&
+               test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 4 &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn | \
                  grep "^author DDDDDDD DDDDDDD <dd@example\.com> " &&
                git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \
@@ -73,8 +73,8 @@ tmp_config_get () {
 test_expect_success 'failure happened without negative side effects' '
        (
                cd aa-work &&
-               test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
-               test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
+               test 6 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" &&
+               test 6 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)"
        )
        '
 
@@ -86,8 +86,8 @@ test_expect_success 'fetch continues after authors-file is fixed' '
        (
                cd aa-work &&
                git svn fetch --authors-file=../svn-authors &&
-               test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" &&
-               test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`"
+               test 8 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" &&
+               test 8 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)"
        )
        '
 
index 6c4c90b03694d2ebe986897b744444fbc00b7125..aeceffaf7b0824b8da673261f523589d3b141619 100755 (executable)
@@ -87,7 +87,7 @@ test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x'
 
 test_expect_success SYMLINKS '"bar" is a symlink that points to "asdf"' '
        test -L x/bar &&
-       (cd x && test xasdf = x"`git cat-file blob HEAD:bar`")
+       (cd x && test xasdf = x"$(git cat-file blob HEAD:bar)")
 '
 
 test_expect_success 'get "bar" => symlink fix from svn' '
@@ -96,7 +96,7 @@ test_expect_success 'get "bar" => symlink fix from svn' '
 
 test_expect_success SYMLINKS '"bar" remains a proper symlink' '
        test -L x/bar &&
-       (cd x && test xdoink = x"`git cat-file blob HEAD:bar`")
+       (cd x && test xdoink = x"$(git cat-file blob HEAD:bar)")
 '
 
 test_done
index d60da63f7aced3e13a411eee661509ae3790e68f..5fa07a369ff06f739a9edea2a8924fc3f19a88ca 100755 (executable)
@@ -16,15 +16,15 @@ test_expect_success 'initialize repo' '
        '
 
 test_expect_success '(supposedly) non-conflicting change from SVN' '
-       test x"`sed -n -e 58p < file`" = x58 &&
-       test x"`sed -n -e 61p < file`" = x61 &&
+       test x"$(sed -n -e 58p < file)" = x58 &&
+       test x"$(sed -n -e 61p < file)" = x61 &&
        svn_cmd co "$svnrepo" tmp &&
        (cd tmp &&
                perl -i.bak -p -e "s/^58$/5588/" file &&
                perl -i.bak -p -e "s/^61$/6611/" file &&
                poke file &&
-               test x"`sed -n -e 58p < file`" = x5588 &&
-               test x"`sed -n -e 61p < file`" = x6611 &&
+               test x"$(sed -n -e 58p < file)" = x5588 &&
+               test x"$(sed -n -e 61p < file)" = x6611 &&
                svn_cmd commit -m "58 => 5588, 61 => 6611"
        )
        '
@@ -38,20 +38,20 @@ test_expect_success 'some unrelated changes to git' "
        "
 
 test_expect_success 'change file but in unrelated area' "
-       test x\"\`sed -n -e 4p < file\`\" = x4 &&
-       test x\"\`sed -n -e 7p < file\`\" = x7 &&
+       test x\"\$(sed -n -e 4p < file)\" = x4 &&
+       test x\"\$(sed -n -e 7p < file)\" = x7 &&
        perl -i.bak -p -e 's/^4\$/4444/' file &&
        perl -i.bak -p -e 's/^7\$/7777/' file &&
-       test x\"\`sed -n -e 4p < file\`\" = x4444 &&
-       test x\"\`sed -n -e 7p < file\`\" = x7777 &&
+       test x\"\$(sed -n -e 4p < file)\" = x4444 &&
+       test x\"\$(sed -n -e 7p < file)\" = x7777 &&
        git commit -m '4 => 4444, 7 => 7777' file &&
        git svn dcommit &&
        svn_cmd up tmp &&
        cd tmp &&
-               test x\"\`sed -n -e 4p < file\`\" = x4444 &&
-               test x\"\`sed -n -e 7p < file\`\" = x7777 &&
-               test x\"\`sed -n -e 58p < file\`\" = x5588 &&
-               test x\"\`sed -n -e 61p < file\`\" = x6611
+               test x\"\$(sed -n -e 4p < file)\" = x4444 &&
+               test x\"\$(sed -n -e 7p < file)\" = x7777 &&
+               test x\"\$(sed -n -e 58p < file)\" = x5588 &&
+               test x\"\$(sed -n -e 61p < file)\" = x6611
        "
 
 test_expect_success 'attempt to dcommit with a dirty index' '
index 2937f4c265b26a92f9ce0634c6e7df578c6c781a..7d7e9d46bc6bf40f52efffede6b369f052c46843 100755 (executable)
@@ -37,7 +37,7 @@ test_expect_success 'import authors with prog and file' '
 test_expect_success 'imported 6 revisions successfully' '
        (
                cd x
-               test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 6
+               test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 6
        )
 '
 
index 65591374938b0d8967e6cbc7fe6a96746304bff0..3bbf341f6a5b176a96bb00c5644d294e13c0cc43 100755 (executable)
@@ -17,8 +17,8 @@ test_expect_success 'git svn clone --stdlayout sets up trunk as master' '
        git svn clone -s "$svnrepo" g &&
        (
                cd g &&
-               test x`git rev-parse --verify refs/remotes/origin/trunk^0` = \
-                    x`git rev-parse --verify refs/heads/master^0`
+               test x$(git rev-parse --verify refs/remotes/origin/trunk^0) = \
+                    x$(git rev-parse --verify refs/heads/master^0)
        )
 '
 
index 24c2421bfc1acd7248fc8094ad76096f12579992..1bb676bedef9d19fdce8bd3c595a979d0b1a9eea 100755 (executable)
@@ -19,7 +19,7 @@ test_expect_success 'load svk depot' "
 uuid=b48289b2-9c08-4d72-af37-0358a40b9c15
 
 test_expect_success 'svk merges were represented coming in' "
-       [ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
+       [ $(git cat-file commit HEAD | grep parent | wc -l) -eq 2 ]
        "
 
 test_done
index 14a938402e099744d6c334b7b5bb2c9ee835be3c..4c5f3c9d418bf6f85f1067b2cb1481bf941ff954 100755 (executable)
@@ -171,10 +171,10 @@ test_expect_success 'A: verify tag/series-A-blob' '
 
 test_expect_success 'A: verify marks output' '
        cat >expect <<-EOF &&
-       :2 `git rev-parse --verify master:file2`
-       :3 `git rev-parse --verify master:file3`
-       :4 `git rev-parse --verify master:file4`
-       :5 `git rev-parse --verify master^0`
+       :2 $(git rev-parse --verify master:file2)
+       :3 $(git rev-parse --verify master:file3)
+       :4 $(git rev-parse --verify master:file4)
+       :5 $(git rev-parse --verify master^0)
        EOF
        test_cmp expect marks.out
 '
@@ -264,8 +264,8 @@ test_expect_success 'A: verify diff' '
        EOF
        git diff-tree -M -r master verify--import-marks >actual &&
        compare_diff_raw expect actual &&
-       test `git rev-parse --verify master:file2` \
-           = `git rev-parse --verify verify--import-marks:copy-of-file2`
+       test $(git rev-parse --verify master:file2) \
+           = $(git rev-parse --verify verify--import-marks:copy-of-file2)
 '
 
 test_expect_success 'A: export marks with large values' '
@@ -364,7 +364,7 @@ test_expect_success 'B: accept branch name "TEMP_TAG"' '
                git prune" &&
        git fast-import <input &&
        test -f .git/TEMP_TAG &&
-       test `git rev-parse master` = `git rev-parse TEMP_TAG^`
+       test $(git rev-parse master) = $(git rev-parse TEMP_TAG^)
 '
 
 test_expect_success 'B: accept empty committer' '
@@ -473,8 +473,8 @@ test_expect_success 'B: fail on invalid committer (5)' '
 ###
 
 test_expect_success 'C: incremental import create pack from stdin' '
-       newf=`echo hi newf | git hash-object -w --stdin` &&
-       oldf=`git rev-parse --verify master:file2` &&
+       newf=$(echo hi newf | git hash-object -w --stdin) &&
+       oldf=$(git rev-parse --verify master:file2) &&
        test_tick &&
        cat >input <<-INPUT_END &&
        commit refs/heads/branch
@@ -499,13 +499,13 @@ test_expect_success 'C: verify pack' '
 '
 
 test_expect_success 'C: validate reuse existing blob' '
-       test $newf = `git rev-parse --verify branch:file2/newf` &&
-       test $oldf = `git rev-parse --verify branch:file2/oldf`
+       test $newf = $(git rev-parse --verify branch:file2/newf) &&
+       test $oldf = $(git rev-parse --verify branch:file2/oldf)
 '
 
 test_expect_success 'C: verify commit' '
        cat >expect <<-EOF &&
-       parent `git rev-parse --verify master^0`
+       parent $(git rev-parse --verify master^0)
        author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
        committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 
@@ -624,7 +624,7 @@ test_expect_success 'E: verify commit' '
 ###
 
 test_expect_success 'F: non-fast-forward update skips' '
-       old_branch=`git rev-parse --verify branch^0` &&
+       old_branch=$(git rev-parse --verify branch^0) &&
        test_tick &&
        cat >input <<-INPUT_END &&
        commit refs/heads/branch
@@ -642,7 +642,7 @@ test_expect_success 'F: non-fast-forward update skips' '
 
        test_must_fail git fast-import <input &&
        # branch must remain unaffected
-       test $old_branch = `git rev-parse --verify branch^0`
+       test $old_branch = $(git rev-parse --verify branch^0)
 '
 
 test_expect_success 'F: verify pack' '
@@ -651,8 +651,8 @@ test_expect_success 'F: verify pack' '
 
 test_expect_success 'F: verify other commit' '
        cat >expect <<-EOF &&
-       tree `git rev-parse branch~1^{tree}`
-       parent `git rev-parse branch~1`
+       tree $(git rev-parse branch~1^{tree})
+       parent $(git rev-parse branch~1)
        author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
        committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 
@@ -667,7 +667,7 @@ test_expect_success 'F: verify other commit' '
 ###
 
 test_expect_success 'G: non-fast-forward update forced' '
-       old_branch=`git rev-parse --verify branch^0` &&
+       old_branch=$(git rev-parse --verify branch^0) &&
        test_tick &&
        cat >input <<-INPUT_END &&
        commit refs/heads/branch
@@ -687,8 +687,8 @@ test_expect_success 'G: verify pack' '
 '
 
 test_expect_success 'G: branch changed, but logged' '
-       test $old_branch != `git rev-parse --verify branch^0` &&
-       test $old_branch = `git rev-parse --verify branch@{1}`
+       test $old_branch != $(git rev-parse --verify branch^0) &&
+       test $old_branch = $(git rev-parse --verify branch@{1})
 '
 
 ###
@@ -763,7 +763,7 @@ test_expect_success 'I: export-pack-edges' '
 
 test_expect_success 'I: verify edge list' '
        cat >expect <<-EOF &&
-       .git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary`
+       .git/objects/pack/pack-.pack: $(git rev-parse --verify export-boundary)
        EOF
        sed -e s/pack-.*pack/pack-.pack/ edges.list >actual &&
        test_cmp expect actual
@@ -795,8 +795,8 @@ test_expect_success 'J: reset existing branch creates empty commit' '
        git fast-import <input
 '
 test_expect_success 'J: branch has 1 commit, empty tree' '
-       test 1 = `git rev-list J | wc -l` &&
-       test 0 = `git ls-tree J | wc -l`
+       test 1 = $(git rev-list J | wc -l) &&
+       test 0 = $(git ls-tree J | wc -l)
 '
 
 test_expect_success 'J: tag must fail on empty branch' '
@@ -838,8 +838,8 @@ test_expect_success 'K: reinit branch with from' '
        git fast-import <input
 '
 test_expect_success 'K: verify K^1 = branch^1' '
-       test `git rev-parse --verify branch^1` \
-               = `git rev-parse --verify K^1`
+       test $(git rev-parse --verify branch^1) \
+               = $(git rev-parse --verify K^1)
 '
 
 ###
@@ -929,7 +929,7 @@ test_expect_success 'L: nested tree copy does not corrupt deltas' '
        git ls-tree L2 g/b/ >tmp &&
        cat tmp | cut -f 2 >actual &&
        test_cmp expect actual &&
-       git fsck `git rev-parse L2`
+       git fsck $(git rev-parse L2)
 '
 
 ###
@@ -1106,7 +1106,7 @@ test_expect_success 'N: copy dirty subdirectory' '
        INPUT_END
 
        git fast-import <input &&
-       test `git rev-parse N2^{tree}` = `git rev-parse N3^{tree}`
+       test $(git rev-parse N2^{tree}) = $(git rev-parse N3^{tree})
 '
 
 test_expect_success 'N: copy directory by id' '
@@ -1503,7 +1503,7 @@ test_expect_success 'O: comments are all skipped' '
        INPUT_END
 
        git fast-import <input &&
-       test `git rev-parse N3` = `git rev-parse O1`
+       test $(git rev-parse N3) = $(git rev-parse O1)
 '
 
 test_expect_success 'O: blank lines not necessary after data commands' '
@@ -1524,7 +1524,7 @@ test_expect_success 'O: blank lines not necessary after data commands' '
        INPUT_END
 
        git fast-import <input &&
-       test `git rev-parse N3` = `git rev-parse O2`
+       test $(git rev-parse N3) = $(git rev-parse O2)
 '
 
 test_expect_success 'O: repack before next test' '
@@ -1570,8 +1570,8 @@ test_expect_success 'O: blank lines not necessary after other commands' '
        INPUT_END
 
        git fast-import <input &&
-       test 8 = `find .git/objects/pack -type f | wc -l` &&
-       test `git rev-parse refs/tags/O3-2nd` = `git rev-parse O3^` &&
+       test 8 = $(find .git/objects/pack -type f | wc -l) &&
+       test $(git rev-parse refs/tags/O3-2nd) = $(git rev-parse O3^) &&
        git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual &&
        test_cmp expect actual
 '
@@ -1631,7 +1631,7 @@ test_expect_success 'P: superproject & submodule mix' '
        data <<DATAEND
        [submodule "sub"]
                path = sub
-               url = "`pwd`/sub"
+               url = "$(pwd)/sub"
        DATAEND
 
        commit refs/heads/subuse1
@@ -1691,7 +1691,7 @@ test_expect_success 'P: verbatim SHA gitlinks' '
        data <<DATAEND
        [submodule "sub"]
                path = sub
-               url = "`pwd`/sub"
+               url = "$(pwd)/sub"
        DATAEND
 
        commit refs/heads/subuse2
@@ -1978,7 +1978,7 @@ test_expect_success 'Q: verify first note for third commit' '
 
 test_expect_success 'Q: verify second notes commit' '
        cat >expect <<-EOF &&
-       parent `git rev-parse --verify refs/notes/foobar~2`
+       parent $(git rev-parse --verify refs/notes/foobar~2)
        author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
        committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 
@@ -2045,7 +2045,7 @@ test_expect_success 'Q: verify third note for first commit' '
 
 test_expect_success 'Q: verify fourth notes commit' '
        cat >expect <<-EOF &&
-       parent `git rev-parse --verify refs/notes/foobar^`
+       parent $(git rev-parse --verify refs/notes/foobar^)
        author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
        committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 
index 66c8b0a371e37f90cff8da0c92f09c8784ec45a2..b5149fde6ecda2b3de5ed60f43c60ab70230289c 100755 (executable)
@@ -163,7 +163,7 @@ test_expect_success 'setup submodule' '
                git add file &&
                git commit -m sub_initial
        ) &&
-       git submodule add "`pwd`/sub" sub &&
+       git submodule add "$(pwd)/sub" sub &&
        git commit -m initial &&
        test_tick &&
        (
@@ -377,7 +377,7 @@ test_expect_success 'full-tree re-shows unmodified files'        '
 
 test_expect_success 'set-up a few more tags for tag export tests' '
        git checkout -f master &&
-       HEAD_TREE=`git show -s --pretty=raw HEAD | grep tree | sed "s/tree //"` &&
+       HEAD_TREE=$(git show -s --pretty=raw HEAD | grep tree | sed "s/tree //") &&
        git tag    tree_tag        -m "tagging a tree" $HEAD_TREE &&
        git tag -a tree_tag-obj    -m "tagging a tree" $HEAD_TREE &&
        git tag    tag-obj_tag     -m "tagging a tag" tree_tag-obj &&
@@ -422,7 +422,7 @@ test_expect_success 'directory becomes symlink'        '
 test_expect_success 'fast-export quotes pathnames' '
        git init crazy-paths &&
        (cd crazy-paths &&
-        blob=`echo foo | git hash-object -w --stdin` &&
+        blob=$(echo foo | git hash-object -w --stdin) &&
         git update-index --add \
                --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \
                --cacheinfo 100644 $blob "path with \"quote\"" \
index d3a5bac754fd8a80a0df0c091fe0769f74f16a4d..2a0ffed870dd8634466bccfd0e435b5a304f8818 100755 (executable)
@@ -100,14 +100,14 @@ test_expect_success 'snapshots: bad tree-ish id (tagged object)' '
        echo object > tag-object &&
        git add tag-object &&
        test_tick && git commit -m "Object to be tagged" &&
-       git tag tagged-object `git hash-object tag-object` &&
+       git tag tagged-object $(git hash-object tag-object) &&
        gitweb_run "p=.git;a=snapshot;h=tagged-object;sf=tgz" &&
        grep "400 - Object is not a tree-ish" gitweb.output
 '
 test_debug 'cat gitweb.output'
 
 test_expect_success 'snapshots: good object id' '
-       ID=`git rev-parse --verify HEAD` &&
+       ID=$(git rev-parse --verify HEAD) &&
        gitweb_run "p=.git;a=snapshot;h=$ID;sf=tgz" &&
        grep "Status: 200 OK" gitweb.output
 '
@@ -173,7 +173,7 @@ test_expect_success DATE_PARSER 'modification: snapshot if-modified-since (unmod
 test_debug 'cat gitweb.headers'
 
 test_expect_success DATE_PARSER 'modification: tree snapshot' '
-       ID=`git rev-parse --verify HEAD^{tree}` &&
+       ID=$(git rev-parse --verify HEAD^{tree}) &&
        HTTP_IF_MODIFIED_SINCE="Wed, 6 Apr 2005 22:14:13 +0000" &&
        export HTTP_IF_MODIFIED_SINCE &&
        test_when_finished "unset HTTP_IF_MODIFIED_SINCE" &&
diff --git a/t/t9827-git-p4-change-filetype.sh b/t/t9827-git-p4-change-filetype.sh
new file mode 100755 (executable)
index 0000000..7433998
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+test_description='git p4 support for file type change'
+
+. ./lib-git-p4.sh
+
+test_expect_success 'start p4d' '
+       start_p4d
+'
+
+test_expect_success 'create files' '
+       (
+               cd "$cli" &&
+               p4 client -o | sed "/LineEnd/s/:.*/:unix/" | p4 client -i &&
+               cat >file1 <<-EOF &&
+               text without any funny substitution business
+               EOF
+               cat >file2 <<-EOF &&
+               second file whose type will change
+               EOF
+               p4 add file1 file2 &&
+               p4 submit -d "add files"
+       )
+'
+
+test_expect_success SYMLINKS 'change file to symbolic link' '
+       git p4 clone --dest="$git" //depot@all &&
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               git config git-p4.skipSubmitEdit true &&
+
+               rm file2 &&
+               ln -s file1 file2 &&
+               git add file2 &&
+               git commit -m "symlink file1 to file2" &&
+               git p4 submit &&
+               p4 filelog -m 1 //depot/file2 >filelog &&
+               grep "(symlink)" filelog
+       )
+'
+
+test_expect_success SYMLINKS 'change symbolic link to file' '
+       git p4 clone --dest="$git" //depot@all &&
+       test_when_finished cleanup_git &&
+       (
+               cd "$git" &&
+               git config git-p4.skipSubmitEdit true &&
+
+               rm file2 &&
+               cat >file2 <<-EOF &&
+               This is another content for the second file.
+               EOF
+               git add file2 &&
+               git commit -m "re-write file2" &&
+               git p4 submit &&
+               p4 filelog -m 1 //depot/file2 >filelog &&
+               grep "(text)" filelog
+       )
+'
+
+test_expect_success 'kill p4d' '
+       kill_p4d
+'
+
+test_done
index b0a6bad8ddb6b2e49b0f5620da92b1ca912136c4..de7152f82713bf797aecd3f53bce6ef006524b7b 100755 (executable)
@@ -43,7 +43,7 @@ test_expect_success \
        echo fake: "$@"
        EOF
        chmod +x "fake browser" &&
-       git config browser.w3m.path "`pwd`/fake browser" &&
+       git config browser.w3m.path "$(pwd)/fake browser" &&
        test_web_browse w3m http://example.com/foo
 '
 
index 16c4d7b516649a13e3f07e081e91e1212afc61a5..bd4b02e9dbf9560cf1285bb6607be83964ecc40a 100644 (file)
@@ -1054,20 +1054,28 @@ test_lazy_prereq NOT_ROOT '
        test "$uid" != 0
 '
 
-# On a filesystem that lacks SANITY, a file can be deleted even if
-# the containing directory doesn't have write permissions, or a file
-# can be accessed even if the containing directory doesn't have read
-# or execute permissions, causing our tests that validate that Git
-# works sensibly in such situations.
+# SANITY is about "can you correctly predict what the filesystem would
+# do by only looking at the permission bits of the files and
+# directories?"  A typical example of !SANITY is running the test
+# suite as root, where a test may expect "chmod -r file && cat file"
+# to fail because file is supposed to be unreadable after a successful
+# chmod.  In an environment (i.e. combination of what filesystem is
+# being used and who is running the tests) that lacks SANITY, you may
+# be able to delete or create a file when the containing directory
+# doesn't have write permissions, or access a file even if the
+# containing directory doesn't have read or execute permissions.
+
 test_lazy_prereq SANITY '
        mkdir SANETESTD.1 SANETESTD.2 &&
 
        chmod +w SANETESTD.1 SANETESTD.2 &&
        >SANETESTD.1/x 2>SANETESTD.2/x &&
        chmod -w SANETESTD.1 &&
+       chmod -r SANETESTD.1/x &&
        chmod -rx SANETESTD.2 ||
        error "bug in test sript: cannot prepare SANETESTD"
 
+       ! test -r SANETESTD.1/x &&
        ! rm SANETESTD.1/x && ! test -f SANETESTD.2/x
        status=$?
 
index 25d855d98b5cc718a6da63824e1c0f9ae39ab77c..0a1c28524668f02d3aa4d073c0c6991652cbf850 100644 (file)
@@ -44,6 +44,10 @@ int main(int ac, char **av)
 {
        struct untracked_cache *uc;
        struct strbuf base = STRBUF_INIT;
+
+       /* Hack to avoid modifying the untracked cache when we read it */
+       ignore_untracked_cache_config = 1;
+
        setup_git_directory();
        if (read_cache() < 0)
                die("unable to read index file");
index c67bf65b347810c576f80a0ac33e3b84f42e1516..c3adcd87b8caa2028785483bbc01d85fd0f7a9d6 100644 (file)
@@ -39,6 +39,130 @@ static void normalize_argv_string(const char **var, const char *input)
                die("Bad value: %s\n", input);
 }
 
+struct test_data {
+       const char *from;  /* input:  transform from this ... */
+       const char *to;    /* output: ... to this.            */
+       const char *alternative; /* output: ... or this.      */
+};
+
+static int test_function(struct test_data *data, char *(*func)(char *input),
+       const char *funcname)
+{
+       int failed = 0, i;
+       char buffer[1024];
+       char *to;
+
+       for (i = 0; data[i].to; i++) {
+               if (!data[i].from)
+                       to = func(NULL);
+               else {
+                       strcpy(buffer, data[i].from);
+                       to = func(buffer);
+               }
+               if (!strcmp(to, data[i].to))
+                       continue;
+               if (!data[i].alternative)
+                       error("FAIL: %s(%s) => '%s' != '%s'\n",
+                               funcname, data[i].from, to, data[i].to);
+               else if (!strcmp(to, data[i].alternative))
+                       continue;
+               else
+                       error("FAIL: %s(%s) => '%s' != '%s', '%s'\n",
+                               funcname, data[i].from, to, data[i].to,
+                               data[i].alternative);
+               failed = 1;
+       }
+       return failed;
+}
+
+static struct test_data basename_data[] = {
+       /* --- POSIX type paths --- */
+       { NULL,              "."    },
+       { "",                "."    },
+       { ".",               "."    },
+       { "..",              ".."   },
+       { "/",               "/"    },
+       { "//",              "/", "//" },
+       { "///",             "/", "//" },
+       { "////",            "/", "//" },
+       { "usr",             "usr"  },
+       { "/usr",            "usr"  },
+       { "/usr/",           "usr"  },
+       { "/usr//",          "usr"  },
+       { "/usr/lib",        "lib"  },
+       { "usr/lib",         "lib"  },
+       { "usr/lib///",      "lib"  },
+
+#if defined(__MINGW32__) || defined(_MSC_VER)
+       /* --- win32 type paths --- */
+       { "\\usr",           "usr"  },
+       { "\\usr\\",         "usr"  },
+       { "\\usr\\\\",       "usr"  },
+       { "\\usr\\lib",      "lib"  },
+       { "usr\\lib",        "lib"  },
+       { "usr\\lib\\\\\\",  "lib"  },
+       { "C:/usr",          "usr"  },
+       { "C:/usr",          "usr"  },
+       { "C:/usr/",         "usr"  },
+       { "C:/usr//",        "usr"  },
+       { "C:/usr/lib",      "lib"  },
+       { "C:usr/lib",       "lib"  },
+       { "C:usr/lib///",    "lib"  },
+       { "C:",              "."    },
+       { "C:a",             "a"    },
+       { "C:/",             "/"    },
+       { "C:///",           "/"    },
+       { "\\",              "\\", "/" },
+       { "\\\\",            "\\", "/" },
+       { "\\\\\\",          "\\", "/" },
+#endif
+       { NULL,              NULL   }
+};
+
+static struct test_data dirname_data[] = {
+       /* --- POSIX type paths --- */
+       { NULL,              "."      },
+       { "",                "."      },
+       { ".",               "."      },
+       { "..",              "."      },
+       { "/",               "/"      },
+       { "//",              "/", "//" },
+       { "///",             "/", "//" },
+       { "////",            "/", "//" },
+       { "usr",             "."      },
+       { "/usr",            "/"      },
+       { "/usr/",           "/"      },
+       { "/usr//",          "/"      },
+       { "/usr/lib",        "/usr"   },
+       { "usr/lib",         "usr"    },
+       { "usr/lib///",      "usr"    },
+
+#if defined(__MINGW32__) || defined(_MSC_VER)
+       /* --- win32 type paths --- */
+       { "\\",              "\\"     },
+       { "\\\\",            "\\\\"   },
+       { "\\usr",           "\\"     },
+       { "\\usr\\",         "\\"     },
+       { "\\usr\\\\",       "\\"     },
+       { "\\usr\\lib",      "\\usr"  },
+       { "usr\\lib",        "usr"    },
+       { "usr\\lib\\\\\\",  "usr"    },
+       { "C:a",             "C:."    },
+       { "C:/",             "C:/"    },
+       { "C:///",           "C:/"    },
+       { "C:/usr",          "C:/"    },
+       { "C:/usr/",         "C:/"    },
+       { "C:/usr//",        "C:/"    },
+       { "C:/usr/lib",      "C:/usr" },
+       { "C:usr/lib",       "C:usr"  },
+       { "C:usr/lib///",    "C:usr"  },
+       { "\\\\\\",          "\\"     },
+       { "\\\\\\\\",        "\\"     },
+       { "C:",              "C:.", "." },
+#endif
+       { NULL,              NULL     }
+};
+
 int main(int argc, char **argv)
 {
        if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
@@ -133,6 +257,12 @@ int main(int argc, char **argv)
                return 0;
        }
 
+       if (argc == 2 && !strcmp(argv[1], "basename"))
+               return test_function(basename_data, basename, argv[1]);
+
+       if (argc == 2 && !strcmp(argv[1], "dirname"))
+               return test_function(dirname_data, dirname, argv[1]);
+
        fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
                argv[1] ? argv[1] : "(there was none)");
        return 1;
index 89c7de2c600ce2781ce666324e703d555937740a..fbe0a27ef3295fe3312fb72a478571bfb450cb25 100644 (file)
 
 #include "git-compat-util.h"
 #include "run-command.h"
+#include "argv-array.h"
+#include "strbuf.h"
 #include <string.h>
 #include <errno.h>
 
+static int number_callbacks;
+static int parallel_next(struct child_process *cp,
+                        struct strbuf *err,
+                        void *cb,
+                        void **task_cb)
+{
+       struct child_process *d = cb;
+       if (number_callbacks >= 4)
+               return 0;
+
+       argv_array_pushv(&cp->args, d->argv);
+       strbuf_addf(err, "preloaded output of a child\n");
+       number_callbacks++;
+       return 1;
+}
+
+static int no_job(struct child_process *cp,
+                 struct strbuf *err,
+                 void *cb,
+                 void **task_cb)
+{
+       strbuf_addf(err, "no further jobs available\n");
+       return 0;
+}
+
+static int task_finished(int result,
+                        struct child_process *cp,
+                        struct strbuf *err,
+                        void *pp_cb,
+                        void *pp_task_cb)
+{
+       strbuf_addf(err, "asking for a quick stop\n");
+       return 1;
+}
+
 int main(int argc, char **argv)
 {
        struct child_process proc = CHILD_PROCESS_INIT;
+       int jobs;
 
        if (argc < 3)
                return 1;
-       proc.argv = (const char **)argv+2;
+       proc.argv = (const char **)argv + 2;
 
        if (!strcmp(argv[1], "start-command-ENOENT")) {
                if (start_command(&proc) < 0 && errno == ENOENT)
@@ -30,6 +68,21 @@ int main(int argc, char **argv)
        if (!strcmp(argv[1], "run-command"))
                exit(run_command(&proc));
 
+       jobs = atoi(argv[2]);
+       proc.argv = (const char **)argv + 3;
+
+       if (!strcmp(argv[1], "run-command-parallel"))
+               exit(run_processes_parallel(jobs, parallel_next,
+                                           NULL, NULL, &proc));
+
+       if (!strcmp(argv[1], "run-command-abort"))
+               exit(run_processes_parallel(jobs, parallel_next,
+                                           NULL, task_finished, &proc));
+
+       if (!strcmp(argv[1], "run-command-no-jobs"))
+               exit(run_processes_parallel(jobs, no_job,
+                                           NULL, task_finished, &proc));
+
        fprintf(stderr, "check usage\n");
        return 1;
 }
index ddc491eff9ca52c4aeeced77c901e5907d215f16..60ea1d5f14e2572df5716da5815143ed26a5be4b 100644 (file)
@@ -11,7 +11,7 @@ int main(int argc, char **argv)
        struct sha1_array array = SHA1_ARRAY_INIT;
        struct strbuf line = STRBUF_INIT;
 
-       while (strbuf_getline(&line, stdin, '\n') != EOF) {
+       while (strbuf_getline(&line, stdin) != EOF) {
                const char *arg;
                unsigned char sha1[20];
 
index 0f0bc5d02f4dcbd67c6d405350e5aaeb39f44bfb..cef4bcc8664a1023de074d1355c358450dc4057e 100755 (executable)
@@ -6,13 +6,13 @@ dd if=/dev/zero bs=1048576 count=100 2>/dev/null |
 while read expect cnt pfx
 do
        case "$expect" in '#'*) continue ;; esac
-       actual=`
+       actual=$(
                {
                        test -z "$pfx" || echo "$pfx"
                        dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null |
                        perl -pe 'y/\000/g/'
                } | ./test-sha1 $cnt
-       `
+       )
        if test "$expect" = "$actual"
        then
                echo "OK: $expect $cnt $pfx"
@@ -51,14 +51,14 @@ exit
 
 while read cnt pfx
 do
-       actual=`
+       actual=$(
                {
                        test -z "$pfx" || echo "$pfx"
                        dd if=/dev/zero bs=1048576 count=$cnt 2>/dev/null |
                        perl -pe 'y/\000/g/'
                } | sha1sum |
                sed -e 's/ .*//'
-       `
+       )
        echo "$actual $cnt $pfx"
 done <<EOF
 0
index 6f3416febaba90f281e95ea605ac6aec10853ef3..94b387b499714911c9dfb6dd0940cb3f25a2397e 100644 (file)
--- a/trailer.c
+++ b/trailer.c
@@ -2,6 +2,7 @@
 #include "string-list.h"
 #include "run-command.h"
 #include "commit.h"
+#include "tempfile.h"
 #include "trailer.h"
 /*
  * Copyright (c) 2013, 2014 Christian Couder <chriscool@tuxfamily.org>
@@ -108,23 +109,23 @@ static char last_non_space_char(const char *s)
        return '\0';
 }
 
-static void print_tok_val(const char *tok, const char *val)
+static void print_tok_val(FILE *outfile, const char *tok, const char *val)
 {
        char c = last_non_space_char(tok);
        if (!c)
                return;
        if (strchr(separators, c))
-               printf("%s%s\n", tok, val);
+               fprintf(outfile, "%s%s\n", tok, val);
        else
-               printf("%s%c %s\n", tok, separators[0], val);
+               fprintf(outfile, "%s%c %s\n", tok, separators[0], val);
 }
 
-static void print_all(struct trailer_item *first, int trim_empty)
+static void print_all(FILE *outfile, struct trailer_item *first, int trim_empty)
 {
        struct trailer_item *item;
        for (item = first; item; item = item->next) {
                if (!trim_empty || strlen(item->value) > 0)
-                       print_tok_val(item->token, item->value);
+                       print_tok_val(outfile, item->token, item->value);
        }
 }
 
@@ -795,14 +796,15 @@ static int has_blank_line_before(struct strbuf **lines, int start)
        return 0;
 }
 
-static void print_lines(struct strbuf **lines, int start, int end)
+static void print_lines(FILE *outfile, struct strbuf **lines, int start, int end)
 {
        int i;
        for (i = start; lines[i] && i < end; i++)
-               printf("%s", lines[i]->buf);
+               fprintf(outfile, "%s", lines[i]->buf);
 }
 
-static int process_input_file(struct strbuf **lines,
+static int process_input_file(FILE *outfile,
+                             struct strbuf **lines,
                              struct trailer_item **in_tok_first,
                              struct trailer_item **in_tok_last)
 {
@@ -818,10 +820,10 @@ static int process_input_file(struct strbuf **lines,
        trailer_start = find_trailer_start(lines, trailer_end);
 
        /* Print lines before the trailers as is */
-       print_lines(lines, 0, trailer_start);
+       print_lines(outfile, lines, 0, trailer_start);
 
        if (!has_blank_line_before(lines, trailer_start - 1))
-               printf("\n");
+               fprintf(outfile, "\n");
 
        /* Parse trailer lines */
        for (i = trailer_start; i < trailer_end; i++) {
@@ -842,13 +844,45 @@ static void free_all(struct trailer_item **first)
        }
 }
 
-void process_trailers(const char *file, int trim_empty, struct string_list *trailers)
+static struct tempfile trailers_tempfile;
+
+static FILE *create_in_place_tempfile(const char *file)
+{
+       struct stat st;
+       struct strbuf template = STRBUF_INIT;
+       const char *tail;
+       FILE *outfile;
+
+       if (stat(file, &st))
+               die_errno(_("could not stat %s"), file);
+       if (!S_ISREG(st.st_mode))
+               die(_("file %s is not a regular file"), file);
+       if (!(st.st_mode & S_IWUSR))
+               die(_("file %s is not writable by user"), file);
+
+       /* Create temporary file in the same directory as the original */
+       tail = strrchr(file, '/');
+       if (tail != NULL)
+               strbuf_add(&template, file, tail - file + 1);
+       strbuf_addstr(&template, "git-interpret-trailers-XXXXXX");
+
+       xmks_tempfile_m(&trailers_tempfile, template.buf, st.st_mode);
+       strbuf_release(&template);
+       outfile = fdopen_tempfile(&trailers_tempfile, "w");
+       if (!outfile)
+               die_errno(_("could not open temporary file"));
+
+       return outfile;
+}
+
+void process_trailers(const char *file, int in_place, int trim_empty, struct string_list *trailers)
 {
        struct trailer_item *in_tok_first = NULL;
        struct trailer_item *in_tok_last = NULL;
        struct trailer_item *arg_tok_first;
        struct strbuf **lines;
        int trailer_end;
+       FILE *outfile = stdout;
 
        /* Default config must be setup first */
        git_config(git_trailer_default_config, NULL);
@@ -856,19 +890,26 @@ void process_trailers(const char *file, int trim_empty, struct string_list *trai
 
        lines = read_input_file(file);
 
+       if (in_place)
+               outfile = create_in_place_tempfile(file);
+
        /* Print the lines before the trailers */
-       trailer_end = process_input_file(lines, &in_tok_first, &in_tok_last);
+       trailer_end = process_input_file(outfile, lines, &in_tok_first, &in_tok_last);
 
        arg_tok_first = process_command_line_args(trailers);
 
        process_trailers_lists(&in_tok_first, &in_tok_last, &arg_tok_first);
 
-       print_all(in_tok_first, trim_empty);
+       print_all(outfile, in_tok_first, trim_empty);
 
        free_all(&in_tok_first);
 
        /* Print the lines after the trailers as is */
-       print_lines(lines, trailer_end, INT_MAX);
+       print_lines(outfile, lines, trailer_end, INT_MAX);
+
+       if (in_place)
+               if (rename_tempfile(&trailers_tempfile, file))
+                       die_errno(_("could not rename temporary file to %s"), file);
 
        strbuf_list_free(lines);
 }
index 8eb25d565e284f54d32b1840ceeb45872dc6efb9..36b40b81761f95742c9c6fe7e94ba89f19aabfde 100644 (file)
--- a/trailer.h
+++ b/trailer.h
@@ -1,6 +1,7 @@
 #ifndef TRAILER_H
 #define TRAILER_H
 
-void process_trailers(const char *file, int trim_empty, struct string_list *trailers);
+void process_trailers(const char *file, int in_place, int trim_empty,
+                     struct string_list *trailers);
 
 #endif /* TRAILER_H */
index 0eb3cf01aa1da857c7340805971e63305d73a6ea..a6bff8b30811c649c82afcdc9e018af1a34ce13c 100644 (file)
@@ -54,7 +54,7 @@ static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
        strbuf_reset(buffer);
        if (debug)
                fprintf(stderr, "Debug: Remote helper: Waiting...\n");
-       if (strbuf_getline(buffer, helper, '\n') == EOF) {
+       if (strbuf_getline(buffer, helper) == EOF) {
                if (debug)
                        fprintf(stderr, "Debug: Remote helper quit.\n");
                return 1;
@@ -137,7 +137,8 @@ static struct child_process *get_helper(struct transport *transport)
        data->no_disconnect_req = 0;
 
        /*
-        * Open the output as FILE* so strbuf_getline() can be used.
+        * Open the output as FILE* so strbuf_getline_*() family of
+        * functions can be used.
         * Do this with duped fd because fclose() will close the fd,
         * and stuff like taking over will require the fd to remain.
         */
index 67f366687c7abf2f6bd9cf31faa6f4ed9e6dc69e..9ae71849d622d088a90bfcab81f9053fccfe79ac 100644 (file)
@@ -481,9 +481,10 @@ static int set_git_option(struct git_transport_options *opts,
        return 1;
 }
 
-static int connect_setup(struct transport *transport, int for_push, int verbose)
+static int connect_setup(struct transport *transport, int for_push)
 {
        struct git_transport_data *data = transport->data;
+       int flags = transport->verbose > 0 ? CONNECT_VERBOSE : 0;
 
        if (data->conn)
                return 0;
@@ -491,7 +492,7 @@ static int connect_setup(struct transport *transport, int for_push, int verbose)
        data->conn = git_connect(data->fd, transport->url,
                                 for_push ? data->options.receivepack :
                                 data->options.uploadpack,
-                                verbose ? CONNECT_VERBOSE : 0);
+                                flags);
 
        return 0;
 }
@@ -501,7 +502,7 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus
        struct git_transport_data *data = transport->data;
        struct ref *refs;
 
-       connect_setup(transport, for_push, 0);
+       connect_setup(transport, for_push);
        get_remote_heads(data->fd[0], NULL, 0, &refs,
                         for_push ? REF_NORMAL : 0,
                         &data->extra_have,
@@ -536,7 +537,7 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.update_shallow = data->options.update_shallow;
 
        if (!data->got_remote_heads) {
-               connect_setup(transport, 0, 0);
+               connect_setup(transport, 0);
                get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0,
                                 NULL, &data->shallow);
                data->got_remote_heads = 1;
@@ -812,7 +813,7 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re
 
        if (!data->got_remote_heads) {
                struct ref *tmp_refs;
-               connect_setup(transport, 1, 0);
+               connect_setup(transport, 1);
 
                get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL,
                                 NULL, &data->shallow);
index 6dccd2d5dd78e0ee71c1ebc771a99010a56db157..cd4bb2c38bdf40f497ece781ce3a9e61de6b4399 100644 (file)
@@ -320,6 +320,7 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
        struct tree_desc_x *tx = xcalloc(n, sizeof(*tx));
        struct strbuf base = STRBUF_INIT;
        int interesting = 1;
+       char *traverse_path;
 
        for (i = 0; i < n; i++)
                tx[i].d = t[i];
@@ -329,7 +330,11 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
                make_traverse_path(base.buf, info->prev, &info->name);
                base.buf[info->pathlen-1] = '/';
                strbuf_setlen(&base, info->pathlen);
+               traverse_path = xstrndup(base.buf, info->pathlen);
+       } else {
+               traverse_path = xstrndup(info->name.path, info->pathlen);
        }
+       info->traverse_path = traverse_path;
        for (;;) {
                int trees_used;
                unsigned long mask, dirmask;
@@ -411,6 +416,8 @@ int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
        for (i = 0; i < n; i++)
                free_extended_entry(tx + i);
        free(tx);
+       free(traverse_path);
+       info->traverse_path = NULL;
        strbuf_release(&base);
        return error;
 }
index 3b2f7bf17d37de5b475c415b41c6abb4281d5469..174eb617dfb9d6a85bcf1e309227c8b724089765 100644 (file)
@@ -59,6 +59,7 @@ enum follow_symlinks_result {
 enum follow_symlinks_result get_tree_entry_follow_symlinks(unsigned char *tree_sha1, const char *name, unsigned char *result, struct strbuf *result_path, unsigned *mode);
 
 struct traverse_info {
+       const char *traverse_path;
        struct traverse_info *prev;
        struct name_entry name;
        int pathlen;
index 5252de4b252070637c1b4badf7989e791f3b8c75..fee21d24e8ab89208b4aa0af7007b7c033b753bc 100644 (file)
@@ -1,4 +1,4 @@
 #!/bin/sh
 
-echo >&2 "fatal: git was built without support for `basename $0` (@@REASON@@)."
+echo >&2 "fatal: git was built without support for $(basename $0) (@@REASON@@)."
 exit 128
index 8e2032f4e592910d6f3336f95019647992113877..9f55cc28b9dd41231644053b49875671f5a505fa 100644 (file)
@@ -498,13 +498,14 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
  * itself - the caller needs to do the final check for the cache
  * entry having more data at the end!
  */
-static int do_compare_entry(const struct cache_entry *ce, const struct traverse_info *info, const struct name_entry *n)
+static int do_compare_entry_piecewise(const struct cache_entry *ce, const struct traverse_info *info, const struct name_entry *n)
 {
        int len, pathlen, ce_len;
        const char *ce_name;
 
        if (info->prev) {
-               int cmp = do_compare_entry(ce, info->prev, &info->name);
+               int cmp = do_compare_entry_piecewise(ce, info->prev,
+                                                    &info->name);
                if (cmp)
                        return cmp;
        }
@@ -522,6 +523,39 @@ static int do_compare_entry(const struct cache_entry *ce, const struct traverse_
        return df_name_compare(ce_name, ce_len, S_IFREG, n->path, len, n->mode);
 }
 
+static int do_compare_entry(const struct cache_entry *ce,
+                           const struct traverse_info *info,
+                           const struct name_entry *n)
+{
+       int len, pathlen, ce_len;
+       const char *ce_name;
+       int cmp;
+
+       /*
+        * If we have not precomputed the traverse path, it is quicker
+        * to avoid doing so.  But if we have precomputed it,
+        * it is quicker to use the precomputed version.
+        */
+       if (!info->traverse_path)
+               return do_compare_entry_piecewise(ce, info, n);
+
+       cmp = strncmp(ce->name, info->traverse_path, info->pathlen);
+       if (cmp)
+               return cmp;
+
+       pathlen = info->pathlen;
+       ce_len = ce_namelen(ce);
+
+       if (ce_len < pathlen)
+               return -1;
+
+       ce_len -= pathlen;
+       ce_name = ce->name + pathlen;
+
+       len = tree_entry_len(n);
+       return df_name_compare(ce_name, ce_len, S_IFREG, n->path, len, n->mode);
+}
+
 static int compare_entry(const struct cache_entry *ce, const struct traverse_info *info, const struct name_entry *n)
 {
        int cmp = do_compare_entry(ce, info, n);
@@ -661,8 +695,19 @@ static int find_cache_pos(struct traverse_info *info,
                                ++o->cache_bottom;
                        continue;
                }
-               if (!ce_in_traverse_path(ce, info))
+               if (!ce_in_traverse_path(ce, info)) {
+                       /*
+                        * Check if we can skip future cache checks
+                        * (because we're already past all possible
+                        * entries in the traverse path).
+                        */
+                       if (info->traverse_path) {
+                               if (strncmp(ce->name, info->traverse_path,
+                                           info->pathlen) > 0)
+                                       break;
+                       }
                        continue;
+               }
                ce_name = ce->name + pfxlen;
                ce_slash = strchr(ce_name, '/');
                if (ce_slash)
index 7b7e72b1201850f0ba494f8fc23a5c7f0e46d3eb..08773d419f17a131c35e8e671bcfe4b174a9ceb3 100644 (file)
--- a/walker.c
+++ b/walker.c
@@ -220,7 +220,7 @@ int walker_targets_stdin(char ***target, const char ***write_ref)
                char *rf_one = NULL;
                char *tg_one;
 
-               if (strbuf_getline(&buf, stdin, '\n') == EOF)
+               if (strbuf_getline_lf(&buf, stdin) == EOF)
                        break;
                tg_one = buf.buf;
                rf_one = strchr(tg_one, '\t');
index 981f810e80008d878d6a5af1331c89dc093c5927..6181a66f1ee2e1e45d7d8b2c88d312746473661f 100644 (file)
@@ -176,10 +176,10 @@ struct worktree **get_worktrees(void)
                        if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
                                continue;
 
-                               if ((linked = get_linked_worktree(d->d_name))) {
-                                       ALLOC_GROW(list, counter + 1, alloc);
-                                       list[counter++] = linked;
-                               }
+                       if ((linked = get_linked_worktree(d->d_name))) {
+                               ALLOC_GROW(list, counter + 1, alloc);
+                               list[counter++] = linked;
+                       }
                }
                closedir(dir);
        }
index c95e2906b850749cbeb109050359b671979969f2..29a45d2654e982dbbb3fc328e16c01713d8a7fb5 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -236,8 +236,24 @@ ssize_t xread(int fd, void *buf, size_t len)
            len = MAX_IO_SIZE;
        while (1) {
                nr = read(fd, buf, len);
-               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
-                       continue;
+               if (nr < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       if (errno == EAGAIN || errno == EWOULDBLOCK) {
+                               struct pollfd pfd;
+                               pfd.events = POLLIN;
+                               pfd.fd = fd;
+                               /*
+                                * it is OK if this poll() failed; we
+                                * want to leave this infinite loop
+                                * only when read() returns with
+                                * success, or an expected failure,
+                                * which would be checked by the next
+                                * call to read(2).
+                                */
+                               poll(&pfd, 1, -1);
+                       }
+               }
                return nr;
        }
 }
@@ -375,6 +391,19 @@ FILE *xfdopen(int fd, const char *mode)
        return stream;
 }
 
+FILE *fopen_for_writing(const char *path)
+{
+       FILE *ret = fopen(path, "w");
+
+       if (!ret && errno == EPERM) {
+               if (!unlink(path))
+                       ret = fopen(path, "w");
+               else
+                       errno = EPERM;
+       }
+       return ret;
+}
+
 int xmkstemp(char *template)
 {
        int fd;
index bba25960b4e3c54a7c1d8861ea895fbe01aa3110..ab4f80d6d0415e449cade48e986c77c933bfecac 100644 (file)
@@ -988,7 +988,7 @@ static char *read_line_from_git_path(const char *filename)
                strbuf_release(&buf);
                return NULL;
        }
-       strbuf_getline(&buf, fp, '\n');
+       strbuf_getline_lf(&buf, fp);
        if (!fclose(fp)) {
                return strbuf_detach(&buf, NULL);
        } else {
@@ -1076,7 +1076,7 @@ static void read_rebase_todolist(const char *fname, struct string_list *lines)
        if (!f)
                die_errno("Could not open file %s for reading",
                          git_path("%s", fname));
-       while (!strbuf_getline(&line, f, '\n')) {
+       while (!strbuf_getline_lf(&line, f)) {
                if (line.len && line.buf[0] == comment_line_char)
                        continue;
                strbuf_trim(&line);
index 625198e0585c52c20c778790c82126efd1b57009..d98f430c912bead3ee5381eafd195dde4d709c47 100644 (file)
@@ -109,7 +109,7 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
        return 0;
 }
 
-static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add_nl, char *dest)
+static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
 {
        xrecord_t **recs;
        int size = 0;
@@ -125,6 +125,12 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add
        if (add_nl) {
                i = recs[count - 1]->size;
                if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
+                       if (needs_cr) {
+                               if (dest)
+                                       dest[size] = '\r';
+                               size++;
+                       }
+
                        if (dest)
                                dest[size] = '\n';
                        size++;
@@ -133,14 +139,58 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int add
        return size;
 }
 
-static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
+static int xdl_recs_copy(xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+{
+       return xdl_recs_copy_0(0, xe, i, count, needs_cr, add_nl, dest);
+}
+
+static int xdl_orig_copy(xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
+{
+       return xdl_recs_copy_0(1, xe, i, count, needs_cr, add_nl, dest);
+}
+
+/*
+ * Returns 1 if the i'th line ends in CR/LF (if it is the last line and
+ * has no eol, the preceding line, if any), 0 if it ends in LF-only, and
+ * -1 if the line ending cannot be determined.
+ */
+static int is_eol_crlf(xdfile_t *file, int i)
 {
-       return xdl_recs_copy_0(0, xe, i, count, add_nl, dest);
+       long size;
+
+       if (i < file->nrec - 1)
+               /* All lines before the last *must* end in LF */
+               return (size = file->recs[i]->size) > 1 &&
+                       file->recs[i]->ptr[size - 2] == '\r';
+       if (!file->nrec)
+               /* Cannot determine eol style from empty file */
+               return -1;
+       if ((size = file->recs[i]->size) &&
+                       file->recs[i]->ptr[size - 1] == '\n')
+               /* Last line; ends in LF; Is it CR/LF? */
+               return size > 1 &&
+                       file->recs[i]->ptr[size - 2] == '\r';
+       if (!i)
+               /* The only line has no eol */
+               return -1;
+       /* Determine eol from second-to-last line */
+       return (size = file->recs[i - 1]->size) > 1 &&
+               file->recs[i - 1]->ptr[size - 2] == '\r';
 }
 
-static int xdl_orig_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
+static int is_cr_needed(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m)
 {
-       return xdl_recs_copy_0(1, xe, i, count, add_nl, dest);
+       int needs_cr;
+
+       /* Match post-images' preceding, or first, lines' end-of-line style */
+       needs_cr = is_eol_crlf(&xe1->xdf2, m->i1 ? m->i1 - 1 : 0);
+       if (needs_cr)
+               needs_cr = is_eol_crlf(&xe2->xdf2, m->i2 ? m->i2 - 1 : 0);
+       /* Look at pre-image's first line, unless we already settled on LF */
+       if (needs_cr)
+               needs_cr = is_eol_crlf(&xe1->xdf1, 0);
+       /* If still undecided, use LF-only */
+       return needs_cr < 0 ? 0 : needs_cr;
 }
 
 static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
@@ -152,16 +202,17 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
        int marker1_size = (name1 ? strlen(name1) + 1 : 0);
        int marker2_size = (name2 ? strlen(name2) + 1 : 0);
        int marker3_size = (name3 ? strlen(name3) + 1 : 0);
+       int needs_cr = is_cr_needed(xe1, xe2, m);
 
        if (marker_size <= 0)
                marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
 
        /* Before conflicting part */
-       size += xdl_recs_copy(xe1, i, m->i1 - i, 0,
+       size += xdl_recs_copy(xe1, i, m->i1 - i, 0, 0,
                              dest ? dest + size : NULL);
 
        if (!dest) {
-               size += marker_size + 1 + marker1_size;
+               size += marker_size + 1 + needs_cr + marker1_size;
        } else {
                memset(dest + size, '<', marker_size);
                size += marker_size;
@@ -170,17 +221,19 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
                        memcpy(dest + size + 1, name1, marker1_size - 1);
                        size += marker1_size;
                }
+               if (needs_cr)
+                       dest[size++] = '\r';
                dest[size++] = '\n';
        }
 
        /* Postimage from side #1 */
-       size += xdl_recs_copy(xe1, m->i1, m->chg1, 1,
+       size += xdl_recs_copy(xe1, m->i1, m->chg1, needs_cr, 1,
                              dest ? dest + size : NULL);
 
        if (style == XDL_MERGE_DIFF3) {
                /* Shared preimage */
                if (!dest) {
-                       size += marker_size + 1 + marker3_size;
+                       size += marker_size + 1 + needs_cr + marker3_size;
                } else {
                        memset(dest + size, '|', marker_size);
                        size += marker_size;
@@ -189,25 +242,29 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
                                memcpy(dest + size + 1, name3, marker3_size - 1);
                                size += marker3_size;
                        }
+                       if (needs_cr)
+                               dest[size++] = '\r';
                        dest[size++] = '\n';
                }
-               size += xdl_orig_copy(xe1, m->i0, m->chg0, 1,
+               size += xdl_orig_copy(xe1, m->i0, m->chg0, needs_cr, 1,
                                      dest ? dest + size : NULL);
        }
 
        if (!dest) {
-               size += marker_size + 1;
+               size += marker_size + 1 + needs_cr;
        } else {
                memset(dest + size, '=', marker_size);
                size += marker_size;
+               if (needs_cr)
+                       dest[size++] = '\r';
                dest[size++] = '\n';
        }
 
        /* Postimage from side #2 */
-       size += xdl_recs_copy(xe2, m->i2, m->chg2, 1,
+       size += xdl_recs_copy(xe2, m->i2, m->chg2, needs_cr, 1,
                              dest ? dest + size : NULL);
        if (!dest) {
-               size += marker_size + 1 + marker2_size;
+               size += marker_size + 1 + needs_cr + marker2_size;
        } else {
                memset(dest + size, '>', marker_size);
                size += marker_size;
@@ -216,6 +273,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
                        memcpy(dest + size + 1, name2, marker2_size - 1);
                        size += marker2_size;
                }
+               if (needs_cr)
+                       dest[size++] = '\r';
                dest[size++] = '\n';
        }
        return size;
@@ -241,21 +300,24 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
                                                  marker_size);
                else if (m->mode & 3) {
                        /* Before conflicting part */
-                       size += xdl_recs_copy(xe1, i, m->i1 - i, 0,
+                       size += xdl_recs_copy(xe1, i, m->i1 - i, 0, 0,
                                              dest ? dest + size : NULL);
                        /* Postimage from side #1 */
-                       if (m->mode & 1)
-                               size += xdl_recs_copy(xe1, m->i1, m->chg1, (m->mode & 2),
+                       if (m->mode & 1) {
+                               int needs_cr = is_cr_needed(xe1, xe2, m);
+
+                               size += xdl_recs_copy(xe1, m->i1, m->chg1, needs_cr, (m->mode & 2),
                                                      dest ? dest + size : NULL);
+                       }
                        /* Postimage from side #2 */
                        if (m->mode & 2)
-                               size += xdl_recs_copy(xe2, m->i2, m->chg2, 0,
+                               size += xdl_recs_copy(xe2, m->i2, m->chg2, 0, 0,
                                                      dest ? dest + size : NULL);
                } else
                        continue;
                i = m->i1 + m->chg1;
        }
-       size += xdl_recs_copy(xe1, i, xe1->xdf2.nrec - i, 0,
+       size += xdl_recs_copy(xe1, i, xe1->xdf2.nrec - i, 0, 0,
                              dest ? dest + size : NULL);
        return size;
 }