tests: quote PYTHON usage
authorMatt Harbison <matt_harbison@yahoo.com>
Tue, 18 Sep 2018 23:47:21 -0400
changeset 50361 5abc47d4ca6bc3f4fc9de93d184b282481b4b2b2
parent 50360 030d558c6456c435b9c2f50249be0838ec27606d
child 50362 fe28267d522349c4642e32c1a7a06dada8515cad
push id953
push usergszorc@mozilla.com
push dateWed, 19 Sep 2018 21:16:09 +0000
tests: quote PYTHON usage Python3 defaults to installing under "Program Files".
tests/test-addremove-similar.t
tests/test-amend.t
tests/test-annotate.t
tests/test-archive.t
tests/test-bad-pull.t
tests/test-basic.t
tests/test-blackbox.t
tests/test-bookmarks-pushpull.t
tests/test-bundle2-format.t
tests/test-bundle2-pushback.t
tests/test-bundle2-remote-changegroup.t
tests/test-censor.t
tests/test-check-config.t
tests/test-check-help.t
tests/test-check-module-imports.t
tests/test-check-py3-compat.t
tests/test-chg.t
tests/test-clone-cgi.t
tests/test-clone.t
tests/test-commit-interactive-curses.t
tests/test-commit-interactive.t
tests/test-commit-multiple.t
tests/test-commit.t
tests/test-conflict.t
tests/test-contrib-dumprevlog.t
tests/test-contrib.t
tests/test-convert-bzr-ghosts.t
tests/test-convert-bzr-treeroot.t
tests/test-convert-bzr.t
tests/test-convert-clonebranches.t
tests/test-convert-git.t
tests/test-convert-hg-source.t
tests/test-convert-hg-svn.t
tests/test-convert-mtn.t
tests/test-convert-p4-filetypes.t
tests/test-convert-svn-move.t
tests/test-convert-svn-sink.t
tests/test-convert-svn-source.t
tests/test-convert.t
tests/test-debugcommands.t
tests/test-diff-binary-file.t
tests/test-diff-color.t
tests/test-diff-newlines.t
tests/test-diff-upgrade.t
tests/test-encoding-align.t
tests/test-encoding.t
tests/test-eol.t
tests/test-extdiff.t
tests/test-extension.t
tests/test-fastannotate-protocol.t
tests/test-fileset-generated.t
tests/test-fix-topology.t
tests/test-fix.t
tests/test-gendoc.t
tests/test-glog-beautifygraph.t
tests/test-glog.t
tests/test-grep.t
tests/test-hardlinks.t
tests/test-help.t
tests/test-hghave.t
tests/test-hgignore.t
tests/test-hgrc.t
tests/test-hgweb-commands.t
tests/test-hgweb-json.t
tests/test-hgweb-no-path-info.t
tests/test-hgweb-no-request-uri.t
tests/test-hgweb-non-interactive.t
tests/test-hgweb.t
tests/test-highlight.t
tests/test-histedit-arguments.t
tests/test-i18n.t
tests/test-impexp-branch.t
tests/test-import-bypass.t
tests/test-import-context.t
tests/test-import-eol.t
tests/test-import.t
tests/test-imports-checker.t
tests/test-inherit-mode.t
tests/test-install.t
tests/test-issue4074.t
tests/test-largefiles-misc.t
tests/test-largefiles.t
tests/test-lfs-largefiles.t
tests/test-lfs-serve-access.t
tests/test-lfs-serve.t
tests/test-lfs-test-server.t
tests/test-lfs.t
tests/test-logexchange.t
tests/test-mactext.t
tests/test-merge-force.t
tests/test-merge-tools.t
tests/test-mq-eol.t
tests/test-mq-missingfiles.t
tests/test-mq-qimport.t
tests/test-mq-qpush-fail.t
tests/test-mq-subrepo-svn.t
tests/test-mq.t
tests/test-narrow-clone-non-narrow-server.t
tests/test-newcgi.t
tests/test-newercgi.t
tests/test-notify-changegroup.t
tests/test-notify.t
tests/test-obsmarker-template.t
tests/test-oldcgi.t
tests/test-pager-legacy.t
tests/test-pager.t
tests/test-parseindex.t
tests/test-patch-offset.t
tests/test-patch.t
tests/test-patchbomb-tls.t
tests/test-patchbomb.t
tests/test-profile.t
tests/test-pull.t
tests/test-purge.t
tests/test-push-cgi.t
tests/test-push-race.t
tests/test-push-warn.t
tests/test-rebase-base-flag.t
tests/test-rebase-dest.t
tests/test-rebase-partial.t
tests/test-relink.t
tests/test-rename-merge2.t
tests/test-repair-strip.t
tests/test-revert.t
tests/test-revset2.t
tests/test-run-tests.t
tests/test-serve.t
tests/test-setdiscovery.t
tests/test-simple-update.t
tests/test-sparse-clone.t
tests/test-sparse.t
tests/test-split.t
tests/test-ssh-bundle1.t
tests/test-ssh-proto.t
tests/test-ssh-repoerror.t
tests/test-ssh.t
tests/test-static-http.t
tests/test-status-rev.t
tests/test-subrepo-svn.t
tests/test-tag.t
tests/test-template-functions.t
tests/test-tools.t
tests/test-transplant.t
tests/test-treemanifest.t
tests/test-walk.t
tests/test-win32text.t
--- a/tests/test-addremove-similar.t
+++ b/tests/test-addremove-similar.t
@@ -1,21 +1,21 @@
   $ hg init rep; cd rep
 
   $ touch empty-file
-  $ $PYTHON -c 'for x in range(10000): print(x)' > large-file
+  $ "$PYTHON" -c 'for x in range(10000): print(x)' > large-file
 
   $ hg addremove
   adding empty-file
   adding large-file
 
   $ hg commit -m A
 
   $ rm large-file empty-file
-  $ $PYTHON -c 'for x in range(10,10000): print(x)' > another-file
+  $ "$PYTHON" -c 'for x in range(10,10000): print(x)' > another-file
 
   $ hg addremove -s50
   adding another-file
   removing empty-file
   removing large-file
   recording removal of large-file as rename to another-file (99% similar)
 
   $ hg commit -m B
@@ -29,40 +29,40 @@ comparing two empty files caused ZeroDiv
   $ hg addremove -s50
   adding another-empty-file
   removing empty-file
 
   $ cd ..
 
   $ hg init rep2; cd rep2
 
-  $ $PYTHON -c 'for x in range(10000): print(x)' > large-file
-  $ $PYTHON -c 'for x in range(50): print(x)' > tiny-file
+  $ "$PYTHON" -c 'for x in range(10000): print(x)' > large-file
+  $ "$PYTHON" -c 'for x in range(50): print(x)' > tiny-file
 
   $ hg addremove
   adding large-file
   adding tiny-file
 
   $ hg commit -m A
 
-  $ $PYTHON -c 'for x in range(70): print(x)' > small-file
+  $ "$PYTHON" -c 'for x in range(70): print(x)' > small-file
   $ rm tiny-file
   $ rm large-file
 
   $ hg addremove -s50
   removing large-file
   adding small-file
   removing tiny-file
   recording removal of tiny-file as rename to small-file (82% similar)
 
   $ hg commit -m B
 
 should be sorted by path for stable result
 
-  $ for i in `$PYTHON $TESTDIR/seq.py 0 9`; do
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 0 9`; do
   >     cp small-file $i
   > done
   $ rm small-file
   $ hg addremove
   adding 0
   adding 1
   adding 2
   adding 3
@@ -83,17 +83,17 @@ should be sorted by path for stable resu
   recording removal of small-file as rename to 7 (100% similar)
   recording removal of small-file as rename to 8 (100% similar)
   recording removal of small-file as rename to 9 (100% similar)
   $ hg commit -m '10 same files'
 
 pick one from many identical files
 
   $ cp 0 a
-  $ rm `$PYTHON $TESTDIR/seq.py 0 9`
+  $ rm `"$PYTHON" $TESTDIR/seq.py 0 9`
   $ hg addremove
   removing 0
   removing 1
   removing 2
   removing 3
   removing 4
   removing 5
   removing 6
@@ -102,21 +102,21 @@ pick one from many identical files
   removing 9
   adding a
   recording removal of 0 as rename to a (100% similar)
   $ hg revert -aq
 
 pick one from many similar files
 
   $ cp 0 a
-  $ for i in `$PYTHON $TESTDIR/seq.py 0 9`; do
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 0 9`; do
   >     echo $i >> $i
   > done
   $ hg commit -m 'make them slightly different'
-  $ rm `$PYTHON $TESTDIR/seq.py 0 9`
+  $ rm `"$PYTHON" $TESTDIR/seq.py 0 9`
   $ hg addremove -s50
   removing 0
   removing 1
   removing 2
   removing 3
   removing 4
   removing 5
   removing 6
--- a/tests/test-amend.t
+++ b/tests/test-amend.t
@@ -245,25 +245,25 @@ Generates history of files having 3 stat
 
  r0: ground (content/missing)
  r1: old state to be amended (content/missing, where missing means removed)
  wc: changes to be included in r1 (content/missing-tracked/untracked)
 
   $ hg init $TESTTMP/wcstates
   $ cd $TESTTMP/wcstates
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove -q --similarity 0
   $ hg commit -m0
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove -q --similarity 0
   $ hg commit -m1
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*-untracked
   $ rm *_*_missing-*
 
 amend r1 to include wc changes
 
   $ hg amend
   saved backup bundle to * (glob) (obsstore-off !)
--- a/tests/test-annotate.t
+++ b/tests/test-annotate.t
@@ -945,23 +945,23 @@ Annotate with orphaned CR (issue5798)
 
   >>> with open('a', 'wb') as f:
   ...     f.write(b'0a\r0b\r\n0c\r0d\r\n0e\n0f\n0g') and None
   $ hg ci -qAm0
   >>> with open('a', 'wb') as f:
   ...     f.write(b'0a\r0b\r\n1c\r1d\r\n0e\n1f\n0g') and None
   $ hg ci -m1
 
-  $ hg annotate -r0 a | $PYTHON "$TESTTMP/substcr.py"
+  $ hg annotate -r0 a | "$PYTHON" "$TESTTMP/substcr.py"
   0: 0a[CR]0b[CR]
   0: 0c[CR]0d[CR]
   0: 0e
   0: 0f
   0: 0g
-  $ hg annotate -r1 a | $PYTHON "$TESTTMP/substcr.py"
+  $ hg annotate -r1 a | "$PYTHON" "$TESTTMP/substcr.py"
   0: 0a[CR]0b[CR]
   1: 1c[CR]1d[CR]
   0: 0e
   1: 1f
   0: 0g
 
   $ cd ..
 
--- a/tests/test-archive.t
+++ b/tests/test-archive.t
@@ -336,59 +336,59 @@ invalid arch type should give 404
   >     stdout = sys.stdout
   > try:
   >     f = util.urlreq.urlopen('http://$LOCALIP:%s/?%s'
   >                     % (os.environ['HGPORT'], requeststr))
   >     stdout.write(f.read())
   > except util.urlerr.httperror as e:
   >     sys.stderr.write(str(e) + '\n')
   > EOF
-  $ $PYTHON getarchive.py "$TIP" gz | gunzip | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" gz | gunzip | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/.hg_archival.txt
   test-archive-1701ef1f1510/.hgsub
   test-archive-1701ef1f1510/.hgsubstate
   test-archive-1701ef1f1510/bar
   test-archive-1701ef1f1510/baz/bletch
   test-archive-1701ef1f1510/foo
   test-archive-1701ef1f1510/subrepo/sub
-  $ $PYTHON getarchive.py "$TIP" bz2 | bunzip2 | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" bz2 | bunzip2 | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/.hg_archival.txt
   test-archive-1701ef1f1510/.hgsub
   test-archive-1701ef1f1510/.hgsubstate
   test-archive-1701ef1f1510/bar
   test-archive-1701ef1f1510/baz/bletch
   test-archive-1701ef1f1510/foo
   test-archive-1701ef1f1510/subrepo/sub
-  $ $PYTHON getarchive.py "$TIP" zip > archive.zip
+  $ "$PYTHON" getarchive.py "$TIP" zip > archive.zip
   $ unzip -t archive.zip
   Archive:  archive.zip
       testing: test-archive-1701ef1f1510/.hg_archival.txt*OK (glob)
       testing: test-archive-1701ef1f1510/.hgsub*OK (glob)
       testing: test-archive-1701ef1f1510/.hgsubstate*OK (glob)
       testing: test-archive-1701ef1f1510/bar*OK (glob)
       testing: test-archive-1701ef1f1510/baz/bletch*OK (glob)
       testing: test-archive-1701ef1f1510/foo*OK (glob)
       testing: test-archive-1701ef1f1510/subrepo/sub*OK (glob)
   No errors detected in compressed data of archive.zip.
 
 test that we can download single directories and files
 
-  $ $PYTHON getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/baz/bletch
-  $ $PYTHON getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
+  $ "$PYTHON" getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
   test-archive-1701ef1f1510/foo
 
 test that we detect file patterns that match no files
 
-  $ $PYTHON getarchive.py "$TIP" gz foobar
+  $ "$PYTHON" getarchive.py "$TIP" gz foobar
   HTTP Error 404: file(s) not found: foobar
 
 test that we reject unsafe patterns
 
-  $ $PYTHON getarchive.py "$TIP" gz relre:baz
+  $ "$PYTHON" getarchive.py "$TIP" gz relre:baz
   HTTP Error 404: file(s) not found: relre:baz
 
   $ killdaemons.py
 
   $ hg archive -t tar test.tar
   $ tar tf test.tar
   test/.hg_archival.txt
   test/.hgsub
@@ -459,17 +459,17 @@ The '-t' should override autodetection
 archive name is stored in the archive, so create similar archives and
 rename them afterwards.
 
   $ hg archive -t tgz tip.tar.gz
   $ mv tip.tar.gz tip1.tar.gz
   $ sleep 1
   $ hg archive -t tgz tip.tar.gz
   $ mv tip.tar.gz tip2.tar.gz
-  $ $PYTHON md5comp.py tip1.tar.gz tip2.tar.gz
+  $ "$PYTHON" md5comp.py tip1.tar.gz tip2.tar.gz
   True
 
   $ hg archive -t zip -p /illegal test.zip
   abort: archive prefix contains illegal components
   [255]
   $ hg archive -t zip -p very/../bad test.zip
 
   $ hg archive --config ui.archivemeta=false -t zip -r 2 test.zip
@@ -593,17 +593,17 @@ configured as GMT.
   > from __future__ import absolute_import, print_function
   > import os
   > import sys
   > print(int(os.stat(sys.argv[1]).st_mtime))
   > EOF
 
   $ hg -R repo archive --prefix tar-extracted archive.tar
   $ (TZ=UTC-3; export TZ; tar xf archive.tar)
-  $ $PYTHON show_mtime.py tar-extracted/a
+  $ "$PYTHON" show_mtime.py tar-extracted/a
   456789012
 
   $ hg -R repo archive --prefix zip-extracted archive.zip
   $ (TZ=UTC-3; export TZ; unzip -q archive.zip)
-  $ $PYTHON show_mtime.py zip-extracted/a
+  $ "$PYTHON" show_mtime.py zip-extracted/a
   456789012
 
   $ cd ..
--- a/tests/test-bad-pull.t
+++ b/tests/test-bad-pull.t
@@ -2,14 +2,14 @@
 
   $ hg clone http://localhost:$HGPORT/ copy
   abort: * (glob)
   [255]
 
   $ test -d copy
   [1]
 
-  $ $PYTHON "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
+  $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
   $ cat dumb.pid >> $DAEMON_PIDS
   $ hg clone http://localhost:$HGPORT/foo copy2
   abort: HTTP Error 404: * (glob)
   [255]
   $ killdaemons.py
--- a/tests/test-basic.t
+++ b/tests/test-basic.t
@@ -63,17 +63,17 @@ Verify that updating to revision 0 via c
   $ cat <<EOF > update_to_rev0.py
   > from mercurial import ui, hg, commands
   > myui = ui.ui.load()
   > repo = hg.repository(myui, path=b'.')
   > commands.update(myui, repo, rev=b"0")
   > EOF
   $ hg up null
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  $ $PYTHON ./update_to_rev0.py
+  $ "$PYTHON" ./update_to_rev0.py
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg identify -n
   0
 
 
 Poke around at hashes:
 
   $ hg manifest --debug
--- a/tests/test-blackbox.t
+++ b/tests/test-blackbox.t
@@ -228,17 +228,17 @@ log rotation
   $ hg blackbox
   1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> init blackboxtest3 exited 0 after * seconds (glob)
   1970/01/01 00:00:00 bob @0000000000000000000000000000000000000000 (5000)> blackbox
   $ mv .hg/blackbox.log .hg/blackbox.log-
   $ mkdir .hg/blackbox.log
   $ sed -e 's/\(.*test1.*\)/#\1/; s#\(.*commit2.*\)#os.rmdir(".hg/blackbox.log")\
   > os.rename(".hg/blackbox.log-", ".hg/blackbox.log")\
   > \1#' $TESTDIR/test-dispatch.py > ../test-dispatch.py
-  $ $PYTHON $TESTDIR/blackbox-readonly-dispatch.py
+  $ "$PYTHON" $TESTDIR/blackbox-readonly-dispatch.py
   running: --debug add foo
   warning: cannot write to blackbox.log: Is a directory (no-windows !)
   warning: cannot write to blackbox.log: $TESTTMP/blackboxtest3/.hg/blackbox.log: Access is denied (windows !)
   adding foo
   result: 0
   running: --debug commit -m commit1 -d 2000-01-01 foo
   warning: cannot write to blackbox.log: Is a directory (no-windows !)
   warning: cannot write to blackbox.log: $TESTTMP/blackboxtest3/.hg/blackbox.log: Access is denied (windows !)
@@ -338,17 +338,17 @@ when using chg, blackbox.log should get 
   $ cat > .hg/hgrc << EOF
   > [blackbox]
   > maxsize = 500B
   > [extensions]
   > # extension change forces chg to restart
   > noop=$TESTTMP/noop.py
   > EOF
 
-  $ $PYTHON -c 'print("a" * 400)' > .hg/blackbox.log
+  $ "$PYTHON" -c 'print("a" * 400)' > .hg/blackbox.log
   $ chg noop
   $ chg noop
   $ chg noop
   $ chg noop
   $ chg noop
 
   $ cat > showsize.py << 'EOF'
   > import os, sys
@@ -357,17 +357,17 @@ when using chg, blackbox.log should get 
   >     size = os.stat(p).st_size
   >     if size >= limit:
   >         desc = '>='
   >     else:
   >         desc = '<'
   >     print('%s: %s %d' % (p, desc, limit))
   > EOF
 
-  $ $PYTHON showsize.py .hg/blackbox*
+  $ "$PYTHON" showsize.py .hg/blackbox*
   .hg/blackbox.log: < 500
   .hg/blackbox.log.1: >= 500
   .hg/blackbox.log.2: >= 500
 
   $ cd ..
 
 With chg, blackbox should not create the log file if the repo is gone
 
--- a/tests/test-bookmarks-pushpull.t
+++ b/tests/test-bookmarks-pushpull.t
@@ -430,17 +430,17 @@ divergent bookmarks
      X@foo                     2:0d2164f0ce0d
      Y                         0:4e3505fd9583
      Z                         2:0d2164f0ce0d
      foo                       -1:000000000000
    * foobar                    1:9b140be10808
 
 (test that too many divergence of bookmark)
 
-  $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
+  $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
   $ hg pull ../a
   pulling from ../a
   searching for changes
   no changes found
   warning: failed to assign numbered name to divergent bookmark X
   divergent bookmark @ stored as @1
   $ hg bookmarks | grep '^   X' | grep -v ':000000000000'
      X                         1:9b140be10808
@@ -458,17 +458,17 @@ divergent bookmarks
   no changes found
   warning: failed to assign numbered name to divergent bookmark X
   divergent bookmark @ stored as @1
   $ hg bookmarks | grep '^   @'
      @                         1:9b140be10808
      @1                        2:0d2164f0ce0d
      @foo                      2:0d2164f0ce0d
 
-  $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
+  $ "$PYTHON" $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
   $ hg bookmarks -d "@1"
 
   $ hg push -f ../a
   pushing to ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
@@ -1077,17 +1077,17 @@ Check hook preventing push (issue4455)
   adding file changes
   added 1 changesets with 1 changes to 1 files
   $ cat >> .hg/hgrc << EOF
   > [paths]
   > local=../issue4455-dest/
   > ssh=ssh://user@dummy/issue4455-dest
   > http=http://localhost:$HGPORT/
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > EOF
   $ cat >> ../issue4455-dest/.hg/hgrc << EOF
   > [hooks]
   > prepushkey=false
   > [web]
   > push_ssl = false
   > allow_push = *
   > EOF
--- a/tests/test-bundle2-format.t
+++ b/tests/test-bundle2-format.t
@@ -227,17 +227,17 @@ Create an extension to test bundle2 API
   >     ui.write(b'parts count:   %i\n' % count)
   > EOF
   $ cat >> $HGRCPATH << EOF
   > [extensions]
   > bundle2=$TESTTMP/bundle2.py
   > [experimental]
   > evolution.createmarkers=True
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
   > [web]
   > push_ssl = false
   > allow_push = *
   > [phases]
   > publish=False
   > EOF
 
--- a/tests/test-bundle2-pushback.t
+++ b/tests/test-bundle2-pushback.t
@@ -31,17 +31,17 @@
   >         op.reply.newpart(b'output', data=b'pushback not enabled')
   >     return result
   > _newhandlechangegroup.params = bundle2.handlechangegroup.params
   > bundle2.parthandlermapping[b'changegroup'] = _newhandlechangegroup
   > EOF
 
   $ cat >> $HGRCPATH <<EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > username = nobody <no.reply@example.com>
   > 
   > [alias]
   > tglog = log -G -T "{desc} [{phase}:{node|short}]"
   > EOF
 
 Set up server repository
 
--- a/tests/test-bundle2-remote-changegroup.t
+++ b/tests/test-bundle2-remote-changegroup.t
@@ -85,22 +85,22 @@ Create an extension to test bundle2 remo
   >         else:
   >             raise Exception('unknown verb')
   > 
   > exchange.getbundle2partsmapping[b'changegroup'] = _getbundlechangegrouppart
   > EOF
 
 Start a simple HTTP server to serve bundles
 
-  $ $PYTHON "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
+  $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
   $ cat dumb.pid >> $DAEMON_PIDS
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
   > EOF
 
   $ hg init repo
 
   $ hg -R repo unbundle $TESTDIR/bundles/rebase.hg
   adding changesets
   adding manifests
--- a/tests/test-censor.t
+++ b/tests/test-censor.t
@@ -301,17 +301,17 @@ Can re-add file after being deleted + ce
   target: no such file in rev 452ec1762369
   [1]
   $ hg cat -r $C4 target
   $ hg cat -r "$H2^^^" target
   Tainted file now super sanitized
 
 Can censor after revlog has expanded to no longer permit inline storage
 
-  $ for x in `$PYTHON $TESTDIR/seq.py 0 50000`
+  $ for x in `"$PYTHON" $TESTDIR/seq.py 0 50000`
   > do
   >   echo "Password: hunter$x" >> target
   > done
   $ hg ci -m 'add 100k passwords'
   $ H2=`hg id --debug -i`
   $ C5=$H2
   $ hg revert -r "$H2^" target
   $ hg ci -m 'cleaned 100k passwords'
--- a/tests/test-check-config.t
+++ b/tests/test-check-config.t
@@ -25,23 +25,23 @@ Sanity check check-config.py
 
   $ cat > files << EOF
   > mercurial/help/config.txt
   > $TESTTMP/testfile.py
   > EOF
 
   $ cd "$TESTDIR"/..
 
-  $ $PYTHON contrib/check-config.py < $TESTTMP/files
+  $ "$PYTHON" contrib/check-config.py < $TESTTMP/files
   foo = ui.configint('ui', 'intdefault', default=42)
   conflict on ui.intdefault: ('int', '42') != ('int', '1')
   at $TESTTMP/testfile.py:12:
   undocumented: ui.doesnotexist (str)
   undocumented: ui.intdefault (int) [42]
   undocumented: ui.intdefault2 (int) [42]
   undocumented: ui.missingbool1 (bool) [True]
   undocumented: ui.missingbool2 (bool)
   undocumented: ui.missingint (int)
 
 New errors are not allowed. Warnings are strongly discouraged.
 
   $ testrepohg files "set:(**.py or **.txt) - tests/**" | sed 's|\\|/|g' |
-  >   $PYTHON contrib/check-config.py
+  >   "$PYTHON" contrib/check-config.py
--- a/tests/test-check-help.t
+++ b/tests/test-check-help.t
@@ -20,10 +20,10 @@
 
   $ cd "$TESTDIR"/..
 
 Check if ":hg:`help TOPIC`" is valid:
 (use "xargs -n1 -t" to see which help commands are executed)
 
   $ testrepohg files 'glob:{hgdemandimport,hgext,mercurial}/**/*.py' \
   > | sed 's|\\|/|g' \
-  > | xargs $PYTHON "$TESTTMP/scanhelptopics.py" \
+  > | xargs "$PYTHON" "$TESTTMP/scanhelptopics.py" \
   > | xargs -n1 hg help --config extensions.phabricator= > /dev/null
--- a/tests/test-check-module-imports.t
+++ b/tests/test-check-module-imports.t
@@ -38,9 +38,9 @@ outputs, which should be fixed later.
   > -X tests/test-hgweb-no-path-info.t \
   > -X tests/test-hgweb-no-request-uri.t \
   > -X tests/test-hgweb-non-interactive.t \
   > -X tests/test-hook.t \
   > -X tests/test-import.t \
   > -X tests/test-imports-checker.t \
   > -X tests/test-lock.py \
   > -X tests/test-verify-repo-operations.py \
-  > | sed 's-\\-/-g' | $PYTHON "$import_checker" -
+  > | sed 's-\\-/-g' | "$PYTHON" "$import_checker" -
--- a/tests/test-check-py3-compat.t
+++ b/tests/test-check-py3-compat.t
@@ -2,17 +2,17 @@
 
   $ . "$TESTDIR/helpers-testrepo.sh"
   $ cd "$TESTDIR"/..
 
 #if no-py3k
   $ testrepohg files 'set:(**.py)' \
   > -X hgdemandimport/demandimportpy2.py \
   > -X mercurial/thirdparty/cbor \
-  > | sed 's|\\|/|g' | xargs $PYTHON contrib/check-py3-compat.py
+  > | sed 's|\\|/|g' | xargs "$PYTHON" contrib/check-py3-compat.py
   contrib/python-zstandard/setup.py not using absolute_import
   contrib/python-zstandard/setup_zstd.py not using absolute_import
   contrib/python-zstandard/tests/common.py not using absolute_import
   contrib/python-zstandard/tests/test_buffer_util.py not using absolute_import
   contrib/python-zstandard/tests/test_compressor.py not using absolute_import
   contrib/python-zstandard/tests/test_compressor_fuzzing.py not using absolute_import
   contrib/python-zstandard/tests/test_data_structures.py not using absolute_import
   contrib/python-zstandard/tests/test_data_structures_fuzzing.py not using absolute_import
@@ -25,23 +25,23 @@
 #endif
 
 #if py3k
   $ testrepohg files 'set:(**.py) - grep(pygments)' \
   > -X hgdemandimport/demandimportpy2.py \
   > -X hgext/fsmonitor/pywatchman \
   > -X mercurial/cffi \
   > -X mercurial/thirdparty \
-  > | sed 's|\\|/|g' | xargs $PYTHON contrib/check-py3-compat.py \
+  > | sed 's|\\|/|g' | xargs "$PYTHON" contrib/check-py3-compat.py \
   > | sed 's/[0-9][0-9]*)$/*)/'
   hgext/convert/transport.py: error importing: <*Error> No module named 'svn.client' (error at transport.py:*) (glob) (?)
   hgext/infinitepush/sqlindexapi.py: error importing: <*Error> No module named 'mysql' (error at sqlindexapi.py:*) (glob) (?)
   mercurial/scmwindows.py: error importing: <ValueError> _type_ 'v' not supported (error at win32.py:*) (no-windows !)
   mercurial/win32.py: error importing: <ValueError> _type_ 'v' not supported (error at win32.py:*) (no-windows !)
   mercurial/windows.py: error importing: <ModuleNotFoundError> No module named 'msvcrt' (error at windows.py:*) (no-windows !)
 
 #endif
 
 #if py3k pygments
   $ testrepohg files 'set:(**.py) and grep(pygments)' | sed 's|\\|/|g' \
-  > | xargs $PYTHON contrib/check-py3-compat.py \
+  > | xargs "$PYTHON" contrib/check-py3-compat.py \
   > | sed 's/[0-9][0-9]*)$/*)/'
 #endif
--- a/tests/test-chg.t
+++ b/tests/test-chg.t
@@ -84,17 +84,17 @@ pager
 enable pager extension globally, but spawns the master server with no tty:
 
   $ chg init pager
   $ cd pager
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > pager =
   > [pager]
-  > pager = $PYTHON $TESTTMP/fakepager.py
+  > pager = "$PYTHON" $TESTTMP/fakepager.py
   > EOF
   $ chg version > /dev/null
   $ touch foo
   $ chg ci -qAm foo
 
 pager should be enabled if the attached client has a tty:
 
   $ chg log -l1 -q --config ui.formatted=True
--- a/tests/test-clone-cgi.t
+++ b/tests/test-clone-cgi.t
@@ -21,19 +21,19 @@ initialize repository
   > wsgicgi.launch(application)
   > HGWEB
   $ chmod 755 hgweb.cgi
 
 try hgweb request
 
   $ . "$TESTDIR/cgienv"
   $ QUERY_STRING="cmd=changegroup&roots=0000000000000000000000000000000000000000"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi >page1 2>&1
-  $ $PYTHON "$TESTDIR/md5sum.py" page1
+  $ "$PYTHON" hgweb.cgi >page1 2>&1
+  $ "$PYTHON" "$TESTDIR/md5sum.py" page1
   1f424bb22ec05c3c6bc866b6e67efe43  page1
 
 make sure headers are sent even when there is no body
 
-  $ QUERY_STRING="cmd=listkeys&namespace=nosuchnamespace" $PYTHON hgweb.cgi
+  $ QUERY_STRING="cmd=listkeys&namespace=nosuchnamespace" "$PYTHON" hgweb.cgi
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 0\r (esc)
   \r (esc)
--- a/tests/test-clone.t
+++ b/tests/test-clone.t
@@ -15,17 +15,17 @@ Prepare repo a:
   $ echo a > a
   $ hg add a
   $ hg commit -m test
   $ echo first line > b
   $ hg add b
 
 Create a non-inlined filelog:
 
-  $ $PYTHON -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
+  $ "$PYTHON" -c 'open("data1", "wb").write(b"".join(b"%d\n" % x for x in range(10000)))'
   $ for j in 0 1 2 3 4 5 6 7 8 9; do
   >   cat data1 >> b
   >   hg commit -m test
   > done
 
 List files in store/data (should show a 'b.d'):
 
 #if reporevlogstore
@@ -559,31 +559,31 @@ iterable in addbranchrevs()
 
   $ cat <<EOF > simpleclone.py
   > from mercurial import ui, hg
   > myui = ui.ui.load()
   > repo = hg.repository(myui, b'a')
   > hg.clone(myui, {}, repo, dest=b"ua")
   > EOF
 
-  $ $PYTHON simpleclone.py
+  $ "$PYTHON" simpleclone.py
   updating to branch default
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ rm -r ua
 
   $ cat <<EOF > branchclone.py
   > from mercurial import ui, hg, extensions
   > myui = ui.ui.load()
   > extensions.loadall(myui)
   > repo = hg.repository(myui, b'a')
   > hg.clone(myui, {}, repo, dest=b"ua", branch=[b"stable",])
   > EOF
 
-  $ $PYTHON branchclone.py
+  $ "$PYTHON" branchclone.py
   adding changesets
   adding manifests
   adding file changes
   added 14 changesets with 14 changes to 3 files
   new changesets acb14030fe0a:0aae7cf88f0d
   updating to branch stable
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ rm -r ua
--- a/tests/test-commit-interactive-curses.t
+++ b/tests/test-commit-interactive-curses.t
@@ -345,17 +345,17 @@ Check spacemovesdown
   no changes to record
   [1]
 
 Check ui.interface logic for the chunkselector
 
 The default interface is text
   $ cp $HGRCPATH.pretest $HGRCPATH
   $ chunkselectorinterface() {
-  > $PYTHON <<EOF
+  > "$PYTHON" <<EOF
   > from mercurial import hg, ui;\
   > repo = hg.repository(ui.ui.load(), ".");\
   > print(repo.ui.interface("chunkselector"))
   > EOF
   > }
   $ chunkselectorinterface
   text
 
--- a/tests/test-commit-interactive.t
+++ b/tests/test-commit-interactive.t
@@ -910,17 +910,17 @@ This tests that translated help message 
   >         return c
   >     else:
   >         return br'\x%02x' % o # escape char setting MSB
   > for l in procutil.stdin:
   >     procutil.stdout.write(
   >         b''.join(escape(c) for c in pycompat.iterbytestr(l)))
   > EOF
 
-  $ hg commit -i --encoding cp932 2>&1 <<EOF | $PYTHON $TESTTMP/escape.py | grep '^y - '
+  $ hg commit -i --encoding cp932 2>&1 <<EOF | "$PYTHON" $TESTTMP/escape.py | grep '^y - '
   > ?
   > q
   > EOF
   y - \x82\xb1\x82\xcc\x95\xcf\x8dX\x82\xf0\x8bL\x98^(yes)
 
   $ LANGUAGE=
 #endif
 
--- a/tests/test-commit-multiple.t
+++ b/tests/test-commit-multiple.t
@@ -110,17 +110,17 @@ now test that we fixed the bug for all s
   >     repo.commit(text=b"y", user=b"test", date=(0, 0))
   >     repo.ui.status(b"POST: len(repo): %d\n" % len(repo))
   > finally:
   >     lock.release()
   >     wlock.release()
   > printfiles(repo, 6)
   > printfiles(repo, 7)
   > __EOF__
-  $ $PYTHON $TESTTMP/committwice.py
+  $ "$PYTHON" $TESTTMP/committwice.py
   PRE: len(repo): 6
   POST: len(repo): 8
   revision 6 files: ['bugfix', 'file1']
   revision 7 files: ['file1']
 
 Do a size-preserving modification outside of that process
   $ echo abcd > bugfix
   $ hg status
--- a/tests/test-commit.t
+++ b/tests/test-commit.t
@@ -649,17 +649,17 @@ verify pathauditor blocks evil filepaths
   > r = hg.repository(u, b'.')
   > def filectxfn(repo, memctx, path):
   >     return context.memfilectx(repo, memctx, path,
   >         b'[hooks]\nupdate = echo owned')
   > c = context.memctx(r, [r[b'tip'].node(), node.nullid],
   >                    b'evil', [notrc], filectxfn, 0)
   > r.commitctx(c)
   > EOF
-  $ $PYTHON evil-commit.py
+  $ "$PYTHON" evil-commit.py
 #if windows
   $ hg co --clean tip
   abort: path contains illegal component: .h\xe2\x80\x8cg\\hgrc (esc)
   [255]
 #else
   $ hg co --clean tip
   abort: path contains illegal component: .h\xe2\x80\x8cg/hgrc (esc)
   [255]
@@ -675,17 +675,17 @@ verify pathauditor blocks evil filepaths
   > r = hg.repository(u, b'.')
   > def filectxfn(repo, memctx, path):
   >     return context.memfilectx(repo, memctx, path,
   >         b'[hooks]\nupdate = echo owned')
   > c = context.memctx(r, [r[b'tip'].node(), node.nullid],
   >                    b'evil', [notrc], filectxfn, 0)
   > r.commitctx(c)
   > EOF
-  $ $PYTHON evil-commit.py
+  $ "$PYTHON" evil-commit.py
   $ hg co --clean tip
   abort: path contains illegal component: HG~1/hgrc
   [255]
 
   $ hg rollback -f
   repository tip rolled back to revision 2 (undo commit)
   $ cat > evil-commit.py <<EOF
   > from __future__ import absolute_import
@@ -695,17 +695,17 @@ verify pathauditor blocks evil filepaths
   > r = hg.repository(u, b'.')
   > def filectxfn(repo, memctx, path):
   >     return context.memfilectx(repo, memctx, path,
   >         b'[hooks]\nupdate = echo owned')
   > c = context.memctx(r, [r[b'tip'].node(), node.nullid],
   >                    b'evil', [notrc], filectxfn, 0)
   > r.commitctx(c)
   > EOF
-  $ $PYTHON evil-commit.py
+  $ "$PYTHON" evil-commit.py
   $ hg co --clean tip
   abort: path contains illegal component: HG8B6C~2/hgrc
   [255]
 
 # test that an unmodified commit template message aborts
 
   $ hg init unmodified_commit_template
   $ cd unmodified_commit_template
--- a/tests/test-conflict.t
+++ b/tests/test-conflict.t
@@ -132,17 +132,17 @@ Verify line splitting of custom conflict
   4
   5
   >>>>>>> merge rev:    test 1
   Hop we are done.
 
 Verify line trimming of custom conflict marker using multi-byte characters
 
   $ hg up -q --clean .
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > fp = open('logfile', 'wb')
   > fp.write(b'12345678901234567890123456789012345678901234567890' +
   >          b'1234567890') # there are 5 more columns for 80 columns
   > 
   > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
   > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
   > 
   > fp.close()
--- a/tests/test-contrib-dumprevlog.t
+++ b/tests/test-contrib-dumprevlog.t
@@ -17,17 +17,17 @@
   $ hg verify
   checking changesets
   checking manifests
   crosschecking files in changesets and manifests
   checking files
   checked 3 changesets with 3 changes to 1 files
 
 Dumping revlog of file a to stdout:
-  $ $PYTHON "$CONTRIBDIR/dumprevlog" .hg/store/data/a.i
+  $ "$PYTHON" "$CONTRIBDIR/dumprevlog" .hg/store/data/a.i
   file: .hg/store/data/a.i
   node: 183d2312b35066fb6b3b449b84efc370d50993d0
   linkrev: 0
   parents: 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000
   length: 15
   -start-
   this is file a
   
@@ -49,24 +49,24 @@ Dumping revlog of file a to stdout:
   this is file a
   adding to file a
   adding more to file a
   
   -end-
 
 Dump all revlogs to file repo.dump:
 
-  $ find .hg/store -name "*.i" | sort | xargs $PYTHON "$CONTRIBDIR/dumprevlog" > ../repo.dump
+  $ find .hg/store -name "*.i" | sort | xargs "$PYTHON" "$CONTRIBDIR/dumprevlog" > ../repo.dump
   $ cd ..
 
 Undumping into repo-b:
 
   $ hg init repo-b
   $ cd repo-b
-  $ $PYTHON "$CONTRIBDIR/undumprevlog" < ../repo.dump
+  $ "$PYTHON" "$CONTRIBDIR/undumprevlog" < ../repo.dump
   .hg/store/00changelog.i
   .hg/store/00manifest.i
   .hg/store/data/a.i
   $ cd ..
 
 Rebuild fncache with clone --pull:
 
   $ hg clone --pull -U repo-b repo-c
--- a/tests/test-contrib.t
+++ b/tests/test-contrib.t
@@ -9,27 +9,27 @@ Test simplemerge command:
   $ echo local > local
   $ cat base >> local
   $ cp local orig
   $ cat base > other
   $ echo other >> other
 
 changing local directly
 
-  $ $PYTHON simplemerge local base other && echo "merge succeeded"
+  $ "$PYTHON" simplemerge local base other && echo "merge succeeded"
   merge succeeded
   $ cat local
   local
   base
   other
   $ cp orig local
 
 printing to stdout
 
-  $ $PYTHON simplemerge -p local base other
+  $ "$PYTHON" simplemerge -p local base other
   local
   base
   other
 
 local:
 
   $ cat local
   local
@@ -38,89 +38,89 @@ local:
 conflicts
 
   $ cp base conflict-local
   $ cp other conflict-other
   $ echo not other >> conflict-local
   $ echo end >> conflict-local
   $ echo end >> conflict-other
 
-  $ $PYTHON simplemerge -p conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p conflict-local base conflict-other
   base
   <<<<<<< conflict-local
   not other
   =======
   other
   >>>>>>> conflict-other
   end
   [1]
 
 1 label
 
-  $ $PYTHON simplemerge -p -L foo conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo conflict-local base conflict-other
   base
   <<<<<<< foo
   not other
   =======
   other
   >>>>>>> conflict-other
   end
   [1]
 
 2 labels
 
-  $ $PYTHON simplemerge -p -L foo -L bar conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo -L bar conflict-local base conflict-other
   base
   <<<<<<< foo
   not other
   =======
   other
   >>>>>>> bar
   end
   [1]
 
 3 labels
 
-  $ $PYTHON simplemerge -p -L foo -L bar -L base conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo -L bar -L base conflict-local base conflict-other
   base
   <<<<<<< foo
   not other
   end
   ||||||| base
   =======
   other
   end
   >>>>>>> bar
   [1]
 
 too many labels
 
-  $ $PYTHON simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other
+  $ "$PYTHON" simplemerge -p -L foo -L bar -L baz -L buz conflict-local base conflict-other
   abort: can only specify three labels.
   [255]
 
 binary file
 
-  $ $PYTHON -c "f = open('binary-local', 'w'); f.write('\x00'); f.close()"
+  $ "$PYTHON" -c "f = open('binary-local', 'w'); f.write('\x00'); f.close()"
   $ cat orig >> binary-local
-  $ $PYTHON simplemerge -p binary-local base other
+  $ "$PYTHON" simplemerge -p binary-local base other
   warning: binary-local looks like a binary file.
   [1]
 
 binary file --text
 
-  $ $PYTHON simplemerge -a -p binary-local base other 2>&1
+  $ "$PYTHON" simplemerge -a -p binary-local base other 2>&1
   warning: binary-local looks like a binary file.
   \x00local (esc)
   base
   other
 
 help
 
-  $ $PYTHON simplemerge --help
+  $ "$PYTHON" simplemerge --help
   simplemerge [OPTS] LOCAL BASE OTHER
   
       Simple three-way file merge utility with a minimal feature set.
   
       Apply to LOCAL the changes necessary to go from BASE to OTHER.
   
       By default, LOCAL is overwritten with the results of this operation.
   
@@ -129,17 +129,17 @@ help
    -a --text        treat all files as text
    -p --print       print results instead of overwriting LOCAL
       --no-minimal  no effect (DEPRECATED)
    -h --help        display help and exit
    -q --quiet       suppress output
 
 wrong number of arguments
 
-  $ $PYTHON simplemerge
+  $ "$PYTHON" simplemerge
   simplemerge: wrong number of arguments
   simplemerge [OPTS] LOCAL BASE OTHER
   
       Simple three-way file merge utility with a minimal feature set.
   
       Apply to LOCAL the changes necessary to go from BASE to OTHER.
   
       By default, LOCAL is overwritten with the results of this operation.
@@ -150,17 +150,17 @@ wrong number of arguments
    -p --print       print results instead of overwriting LOCAL
       --no-minimal  no effect (DEPRECATED)
    -h --help        display help and exit
    -q --quiet       suppress output
   [1]
 
 bad option
 
-  $ $PYTHON simplemerge --foo -p local base other
+  $ "$PYTHON" simplemerge --foo -p local base other
   simplemerge: option --foo not recognized
   simplemerge [OPTS] LOCAL BASE OTHER
   
       Simple three-way file merge utility with a minimal feature set.
   
       Apply to LOCAL the changes necessary to go from BASE to OTHER.
   
       By default, LOCAL is overwritten with the results of this operation.
--- a/tests/test-convert-bzr-ghosts.t
+++ b/tests/test-convert-bzr-ghosts.t
@@ -16,17 +16,17 @@ ghost revisions
   $ mkdir test-ghost-revisions
   $ cd test-ghost-revisions
   $ bzr init -q source
   $ cd source
   $ echo content > somefile
   $ bzr add -q somefile
   $ bzr commit -q -m 'Initial layout setup'
   $ echo morecontent >> somefile
-  $ $PYTHON ../../ghostcreator.py 'Commit with ghost revision' ghostrev
+  $ "$PYTHON" ../../ghostcreator.py 'Commit with ghost revision' ghostrev
   $ cd ..
   $ hg convert source source-hg
   initializing destination source-hg repository
   scanning source...
   sorting...
   converting...
   1 Initial layout setup
   0 Commit with ghost revision
--- a/tests/test-convert-bzr-treeroot.t
+++ b/tests/test-convert-bzr-treeroot.t
@@ -15,17 +15,17 @@ change the id of the tree root
 
   $ mkdir test-change-treeroot-id
   $ cd test-change-treeroot-id
   $ bzr init -q source
   $ cd source
   $ echo content > file
   $ bzr add -q file
   $ bzr commit -q -m 'Initial add'
-  $ $PYTHON ../../treeset.py 'Changed root' new
+  $ "$PYTHON" ../../treeset.py 'Changed root' new
   $ cd ..
   $ hg convert source source-hg
   initializing destination source-hg repository
   scanning source...
   sorting...
   converting...
   1 Initial add
   0 Changed root
--- a/tests/test-convert-bzr.t
+++ b/tests/test-convert-bzr.t
@@ -124,20 +124,20 @@ merge
   $ echo content > a
   $ echo content2 > b
   $ bzr add -q a b
   $ bzr commit -q -m 'Initial add'
   $ cd ..
   $ bzr branch -q source source-improve
   $ cd source
   $ echo more >> a
-  $ $PYTHON ../helper.py 'Editing a' 100
+  $ "$PYTHON" ../helper.py 'Editing a' 100
   $ cd ../source-improve
   $ echo content3 >> b
-  $ $PYTHON ../helper.py 'Editing b' 200
+  $ "$PYTHON" ../helper.py 'Editing b' 200
   $ cd ../source
   $ bzr merge -q ../source-improve
   $ bzr commit -q -m 'Merged improve branch'
   $ cd ..
   $ hg convert --datesort source source-hg
   initializing destination source-hg repository
   scanning source...
   sorting...
--- a/tests/test-convert-clonebranches.t
+++ b/tests/test-convert-clonebranches.t
@@ -37,17 +37,17 @@ Miss perl... sometimes
   > 
   > r = re.compile(r'^(?:\d+|pulling from)')
   > sys.stdout.writelines([l for l in sys.stdin if r.search(l)])
   > EOF
 
 convert
 
   $ hg convert -v --config convert.hg.clonebranches=1 source dest |
-  >     $PYTHON filter.py
+  >     "$PYTHON" filter.py
   3 adda
   2 changea
   1 addb
   pulling from default into branch0
   1 changesets found
   0 mergeab
   pulling from default into branch0
   1 changesets found
@@ -70,17 +70,17 @@ Add a merge with both parents and child 
   $ hg branch branch3
   marked working directory as branch branch3
   $ hg ci -qAm c3
   $ cd ..
 
 incremental conversion
 
   $ hg convert -v --config convert.hg.clonebranches=1 source dest |
-  >     $PYTHON filter.py
+  >     "$PYTHON" filter.py
   2 c1
   pulling from branch0 into branch1
   4 changesets found
   1 c2
   pulling from branch0 into branch2
   4 changesets found
   0 c3
   pulling from branch1 into branch3
--- a/tests/test-convert-git.t
+++ b/tests/test-convert-git.t
@@ -415,34 +415,34 @@ renamelimit config option works
     copy-source
 
 test binary conversion (issue1359)
 
   $ count=19
   $ mkdir git-repo3
   $ cd git-repo3
   $ git init-db >/dev/null 2>/dev/null
-  $ $PYTHON -c 'import struct; open("b", "wb").write(b"".join([struct.Struct(">B").pack(i) for i in range(256)])*16)'
+  $ "$PYTHON" -c 'import struct; open("b", "wb").write(b"".join([struct.Struct(">B").pack(i) for i in range(256)])*16)'
   $ git add b
   $ commit -a -m addbinary
   $ cd ..
 
 convert binary file
 
   $ hg convert git-repo3 git-repo3-hg
   initializing destination git-repo3-hg repository
   scanning source...
   sorting...
   converting...
   0 addbinary
   updating bookmarks
   $ cd git-repo3-hg
   $ hg up -C
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON -c 'from __future__ import print_function; print(len(open("b", "rb").read()))'
+  $ "$PYTHON" -c 'from __future__ import print_function; print(len(open("b", "rb").read()))'
   4096
   $ cd ..
 
 test author vs committer
 
   $ mkdir git-repo4
   $ cd git-repo4
   $ git init-db >/dev/null 2>/dev/null
--- a/tests/test-convert-hg-source.t
+++ b/tests/test-convert-hg-source.t
@@ -125,17 +125,17 @@ check shamap LF and CRLF handling
 
   $ cat > rewrite.py <<EOF
   > import sys
   > # Interlace LF and CRLF
   > lines = [(l.rstrip() + ((i % 2) and b'\n' or b'\r\n'))
   >          for i, l in enumerate(open(sys.argv[1], 'rb'))]
   > open(sys.argv[1], 'wb').write(b''.join(lines))
   > EOF
-  $ $PYTHON rewrite.py new/.hg/shamap
+  $ "$PYTHON" rewrite.py new/.hg/shamap
   $ cd orig
   $ hg up -qC 1
   $ echo foo >> foo
   $ hg ci -qm 'change foo again'
   $ hg up -qC 2
   $ echo foo >> foo
   $ hg ci -qm 'change foo again again'
   $ cd ..
--- a/tests/test-convert-hg-svn.t
+++ b/tests/test-convert-hg-svn.t
@@ -7,19 +7,19 @@
   $ cat <<EOF >> $HGRCPATH
   > [extensions]
   > convert =
   > mq =
   > EOF
 
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
   $ svnadmin create "$SVNREPOPATH"
   $ cat > "$SVNREPOPATH"/hooks/pre-revprop-change <<EOF
   > #!/bin/sh
   > 
   > REPOS="$1"
   > REV="$2"
--- a/tests/test-convert-mtn.t
+++ b/tests/test-convert-mtn.t
@@ -38,17 +38,17 @@ create monotone repository
 
   $ mtn db init --db=repo.mtn
   $ mtn --db=repo.mtn --branch=com.selenic.test setup workingdir
   $ cd workingdir
   $ echo a > a
   $ mkdir dir
   $ echo b > dir/b
   $ echo d > dir/d
-  $ $PYTHON -c 'open("bin", "wb").write(b"a\\x00b") and None'
+  $ "$PYTHON" -c 'open("bin", "wb").write(b"a\\x00b") and None'
   $ echo c > c
   $ mtn add a dir/b dir/d c bin
   mtn: adding 'a' to workspace manifest
   mtn: adding 'bin' to workspace manifest
   mtn: adding 'c' to workspace manifest
   mtn: adding 'dir' to workspace manifest
   mtn: adding 'dir/b' to workspace manifest
   mtn: adding 'dir/d' to workspace manifest
@@ -60,17 +60,17 @@ update monotone working directory
 
   $ mtn mv a dir/a
   mtn: skipping 'dir', already accounted for in workspace
   mtn: renaming 'a' to 'dir/a' in workspace manifest
   $ echo a >> dir/a
   $ echo b >> dir/b
   $ mtn drop c
   mtn: dropping 'c' from workspace manifest
-  $ $PYTHON -c 'open("bin", "wb").write(b"b\\x00c") and None'
+  $ "$PYTHON" -c 'open("bin", "wb").write(b"b\\x00c") and None'
   $ mtn ci -m update1
   mtn: beginning commit on branch 'com.selenic.test'
   mtn: committed revision 51d0a982464573a2a2cf5ee2c9219c652aaebeff
   $ cd ..
 
 convert once
 
   $ hg convert -s mtn repo.mtn
--- a/tests/test-convert-p4-filetypes.t
+++ b/tests/test-convert-p4-filetypes.t
@@ -47,17 +47,17 @@ not testing these
   >          ;;
   >       symlink*)
   >          echo "this is target $T" >target_$T2
   >          ln -s target_$T file_$T2
   >          p4 add target_$T2
   >          p4 add -t $T file_$T2
   >          ;;
   >       binary*)
-  >          $PYTHON -c "open('file_$T2', 'wb').write(b'this is $T')"
+  >          "$PYTHON" -c "open('file_$T2', 'wb').write(b'this is $T')"
   >          p4 add -t $T file_$T2
   >          ;;
   >       *)
   >          echo "this is $T" >file_$T2
   >          p4 add -t $T file_$T2
   >          ;;
   >    esac
   > done
--- a/tests/test-convert-svn-move.t
+++ b/tests/test-convert-svn-move.t
@@ -4,19 +4,19 @@
   > [extensions]
   > convert =
   > EOF
 
   $ svnadmin create svn-repo
   $ svnadmin load -q svn-repo < "$TESTDIR/svn/move.svndump"
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
 Convert trunk and branches
 
   $ hg convert --datesort "$SVNREPOURL"/subproject A-hg
   initializing destination A-hg repository
   scanning source...
   sorting...
--- a/tests/test-convert-svn-sink.t
+++ b/tests/test-convert-svn-sink.t
@@ -5,17 +5,17 @@
   >     (
   >        cd $1;
   >        svn up -q;
   >        svn st -v | sed 's/  */ /g' | sort
   >        limit=''
   >        if [ $2 -gt 0 ]; then
   >            limit="--limit=$2"
   >        fi
-  >        svn log --xml -v $limit | $PYTHON "$TESTDIR/svnxml.py"
+  >        svn log --xml -v $limit | "$PYTHON" "$TESTDIR/svnxml.py"
   >     )
   > }
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
   > EOF
 
--- a/tests/test-convert-svn-source.t
+++ b/tests/test-convert-svn-source.t
@@ -9,19 +9,19 @@
   > convert =
   > [convert]
   > svn.trunk = mytrunk
   > EOF
 
   $ svnadmin create svn-repo
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
   $ INVALIDREVISIONID=svn:x2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk@1
   $ VALIDREVISIONID=svn:a2147622-4a9f-4db4-a8d3-13562ff547b2/proj%20B/mytrunk/mytrunk@1
 
 Now test that it works with trunk/tags layout, but no branches yet.
 
 Initial svn import
 
--- a/tests/test-convert.t
+++ b/tests/test-convert.t
@@ -477,17 +477,17 @@ test pre and post conversion actions
 
 converting empty dir should fail "nicely
 
   $ mkdir emptydir
 
 override $PATH to ensure p4 not visible; use $PYTHON in case we're
 running from a devel copy, not a temp installation
 
-  $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
+  $ PATH="$BINDIR" "$PYTHON" "$BINDIR"/hg convert emptydir
   assuming destination emptydir-hg
   initializing destination emptydir-hg repository
   emptydir does not look like a CVS checkout
   $TESTTMP/emptydir does not look like a Git repository
   emptydir does not look like a Subversion repository
   emptydir is not a local Mercurial repository
   emptydir does not look like a darcs repository
   emptydir does not look like a monotone repository
--- a/tests/test-debugcommands.t
+++ b/tests/test-debugcommands.t
@@ -539,17 +539,17 @@ Test internal debugstacktrace command
   >     g()
   > def g():
   >     util.dst('hello from g\\n', skip=1)
   >     h()
   > def h():
   >     util.dst('hi ...\\nfrom h hidden in g', 1, depth=2)
   > f()
   > EOF
-  $ $PYTHON debugstacktrace.py
+  $ "$PYTHON" debugstacktrace.py
   stacktrace at:
    debugstacktrace.py:12 in * (glob)
    debugstacktrace.py:5  in f
   hello from g at:
    debugstacktrace.py:12 in * (glob)
    debugstacktrace.py:6  in f
   hi ...
   from h hidden in g at:
--- a/tests/test-diff-binary-file.t
+++ b/tests/test-diff-binary-file.t
@@ -78,17 +78,17 @@
 Test text mode with extended git-style diff format
   $ hg init b
   $ cd b
   $ cat > writebin.py <<EOF
   > import sys
   > path = sys.argv[1]
   > open(path, 'wb').write(b'\x00\x01\x02\x03')
   > EOF
-  $ $PYTHON writebin.py binfile.bin
+  $ "$PYTHON" writebin.py binfile.bin
   $ hg add binfile.bin
   $ hg ci -m 'add binfile.bin'
 
   $ echo >> binfile.bin
   $ hg ci -m 'change binfile.bin'
 
   $ hg diff --git -a -r 0 -r 1
   diff --git a/binfile.bin b/binfile.bin
--- a/tests/test-diff-color.t
+++ b/tests/test-diff-color.t
@@ -391,22 +391,22 @@ test inline color diff
   [diff.deleted|-][diff.deleted.unchanged|three of those lines ][diff.deleted.changed|will]
   [diff.deleted|-][diff.deleted.changed|collapse][diff.deleted.unchanged| onto one]
   [diff.deleted|-][diff.deleted.changed|(to see if it works)]
   [diff.inserted|+][diff.inserted.unchanged|three of those lines ][diff.inserted.changed|have]
   [diff.inserted|+][diff.inserted.changed|collapsed][diff.inserted.unchanged| onto one]
 
 multibyte character shouldn't be broken up in word diff:
 
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > with open("utf8", "wb") as f:
   >     f.write(b"blah \xe3\x82\xa2 blah\n")
   > EOF
   $ hg ci -Am 'add utf8 char' utf8
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > with open("utf8", "wb") as f:
   >     f.write(b"blah \xe3\x82\xa4 blah\n")
   > EOF
   $ hg ci -m 'slightly change utf8 char' utf8
 
   $ hg diff --config diff.word-diff=True --color=debug -c.
   [diff.diffline|diff --git a/utf8 b/utf8]
   [diff.file_a|--- a/utf8]
--- a/tests/test-diff-newlines.t
+++ b/tests/test-diff-newlines.t
@@ -1,11 +1,11 @@
   $ hg init
 
-  $ $PYTHON -c 'open("a", "wb").write(b"confuse str.splitlines\nembedded\rnewline\n")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"confuse str.splitlines\nembedded\rnewline\n")'
   $ hg ci -Ama -d '1 0'
   adding a
 
   $ echo clean diff >> a
   $ hg ci -mb -d '2 0'
 
   $ hg diff -r0 -r1
   diff -r 107ba6f817b5 -r 310ce7989cdc a
--- a/tests/test-diff-upgrade.t
+++ b/tests/test-diff-upgrade.t
@@ -11,27 +11,27 @@
   $ cd repo
 
 
 
 make a combination of new, changed and deleted file
 
   $ echo regular > regular
   $ echo rmregular > rmregular
-  $ $PYTHON -c "open('bintoregular', 'wb').write(b'\0')"
+  $ "$PYTHON" -c "open('bintoregular', 'wb').write(b'\0')"
   $ touch rmempty
   $ echo exec > exec
   $ chmod +x exec
   $ echo rmexec > rmexec
   $ chmod +x rmexec
   $ echo setexec > setexec
   $ echo unsetexec > unsetexec
   $ chmod +x unsetexec
   $ echo binary > binary
-  $ $PYTHON -c "open('rmbinary', 'wb').write(b'\0')"
+  $ "$PYTHON" -c "open('rmbinary', 'wb').write(b'\0')"
   $ hg ci -Am addfiles
   adding binary
   adding bintoregular
   adding exec
   adding regular
   adding rmbinary
   adding rmempty
   adding rmexec
@@ -45,18 +45,18 @@ make a combination of new, changed and d
   $ rm rmregular
   $ echo exec >> exec
   $ echo newexec > newexec
   $ echo bintoregular > bintoregular
   $ chmod +x newexec
   $ rm rmexec
   $ chmod +x setexec
   $ chmod -x unsetexec
-  $ $PYTHON -c "open('binary', 'wb').write(b'\0\0')"
-  $ $PYTHON -c "open('newbinary', 'wb').write(b'\0')"
+  $ "$PYTHON" -c "open('binary', 'wb').write(b'\0\0')"
+  $ "$PYTHON" -c "open('newbinary', 'wb').write(b'\0')"
   $ rm rmbinary
   $ hg addremove -s 0
   adding newbinary
   adding newempty
   adding newexec
   adding newregular
   removing rmbinary
   removing rmempty
--- a/tests/test-encoding-align.t
+++ b/tests/test-encoding-align.t
@@ -1,15 +1,15 @@
 Test alignment of multibyte characters
 
   $ HGENCODING=utf-8
   $ export HGENCODING
   $ hg init t
   $ cd t
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > # (byte, width) = (6, 4)
   > s = b"\xe7\x9f\xad\xe5\x90\x8d"
   > # (byte, width) = (7, 7): odd width is good for alignment test
   > m = b"MIDDLE_"
   > # (byte, width) = (18, 12)
   > l = b"\xe9\x95\xb7\xe3\x81\x84\xe9\x95\xb7\xe3\x81\x84\xe5\x90\x8d\xe5\x89\x8d"
   > f = open('s', 'wb'); f.write(s); f.close()
   > f = open('m', 'wb'); f.write(m); f.close()
--- a/tests/test-encoding.t
+++ b/tests/test-encoding.t
@@ -9,17 +9,17 @@ we need a repo with some legacy latin-1 
   adding changesets
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files
   new changesets 1e78a93102a3:0e5b7e3f9c4a (2 drafts)
   (run 'hg update' to get a working copy)
   $ hg co
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > f = open('latin-1', 'wb'); f.write(b"latin-1 e' encoded: \xe9"); f.close()
   > f = open('utf-8', 'wb'); f.write(b"utf-8 e' encoded: \xc3\xa9"); f.close()
   > f = open('latin-1-tag', 'wb'); f.write(b"\xe9"); f.close()
   > EOF
 
 should fail with encoding error
 
   $ echo "plain old ascii" > a
--- a/tests/test-eol.t
+++ b/tests/test-eol.t
@@ -68,17 +68,17 @@ Set up helpers
   >     echo '% a.txt'
   >     cat a.txt
   >     echo '% hg cat a.txt'
   >     hg cat a.txt
   >     printf "fourth${EOL}" >> a.txt
   >     echo '% a.txt'
   >     cat a.txt
   >     hg diff
-  >     $PYTHON ../switch-eol.py $1 a.txt
+  >     "$PYTHON" ../switch-eol.py $1 a.txt
   >     echo '% hg diff only reports a single changed line:'
   >     hg diff
   >     echo "% reverting back to $1 format"
   >     hg revert a.txt
   >     cat a.txt
   >     printf "first\r\nsecond\n" > mixed.txt
   >     hg add mixed.txt
   >     echo "% hg commit of inconsistent .txt file marked as binary (should work)"
--- a/tests/test-extdiff.t
+++ b/tests/test-extdiff.t
@@ -260,17 +260,17 @@ Prepare custom diff/edit tool:
   $ chmod +x 'diff tool.py'
 #endif
 
 will change to /tmp/extdiff.TMP and populate directories a.TMP and a
 and start tool
 
 #if windows
   $ cat > 'diff tool.bat' << EOF
-  > @$PYTHON "`pwd`/diff tool.py"
+  > @"$PYTHON" "`pwd`/diff tool.py"
   > EOF
   $ hg extdiff -p "`pwd`/diff tool.bat"
   [1]
 #else
   $ hg extdiff -p "`pwd`/diff tool.py"
   [1]
 #endif
 
--- a/tests/test-extension.t
+++ b/tests/test-extension.t
@@ -140,17 +140,17 @@ Check hgweb's load order of extensions a
   > from mercurial import demandimport; demandimport.enable()
   > from mercurial.hgweb import hgweb
   > from mercurial.hgweb import wsgicgi
   > application = hgweb(b'.', b'test repo')
   > wsgicgi.launch(application)
   > EOF
   $ . "$TESTDIR/cgienv"
 
-  $ PATH_INFO='/' SCRIPT_NAME='' $PYTHON hgweb.cgi \
+  $ PATH_INFO='/' SCRIPT_NAME='' "$PYTHON" hgweb.cgi \
   >    | grep '^[0-9]) ' # ignores HTML output
   1) foo imported
   1) bar imported
   2) foo uisetup
   2) bar uisetup
   3) foo extsetup
   3) bar extsetup
   4) foo reposetup
@@ -159,17 +159,17 @@ Check hgweb's load order of extensions a
 (check that revset predicate foo() and bar() are available)
 
 #if msys
   $ PATH_INFO='//shortlog'
 #else
   $ PATH_INFO='/shortlog'
 #endif
   $ export PATH_INFO
-  $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' $PYTHON hgweb.cgi \
+  $ SCRIPT_NAME='' QUERY_STRING='rev=foo() and bar()' "$PYTHON" hgweb.cgi \
   >     | grep '<a href="/rev/[0-9a-z]*">'
      <a href="/rev/c24b9ac61126">add file</a>
 
   $ echo 'foo = !' >> $HGRCPATH
   $ echo 'bar = !' >> $HGRCPATH
 
 Check "from __future__ import absolute_import" support for external libraries
 
--- a/tests/test-fastannotate-protocol.t
+++ b/tests/test-fastannotate-protocol.t
@@ -1,11 +1,11 @@
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > [extensions]
   > fastannotate=
   > [fastannotate]
   > mainbranch=@
   > EOF
 
   $ HGMERGE=true; export HGMERGE
 
--- a/tests/test-fileset-generated.t
+++ b/tests/test-fileset-generated.t
@@ -1,21 +1,21 @@
   $ hg init
 
 Set up history and working copy
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove -q --similarity 0
   $ hg commit -m first
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove -q --similarity 0
   $ hg commit -m second
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*-untracked
   $ rm *_*_missing-*
 
 Test status
 
   $ hg st -A 'set:modified()'
   M content1_content1_content3-tracked
--- a/tests/test-fix-topology.t
+++ b/tests/test-fix-topology.t
@@ -4,30 +4,30 @@ A script that implements uppercasing all
   $ cat > $UPPERCASEPY <<EOF
   > import sys
   > from mercurial.utils.procutil import setbinary
   > setbinary(sys.stdin)
   > setbinary(sys.stdout)
   > sys.stdout.write(sys.stdin.read().upper())
   > EOF
   $ TESTLINES="foo\nbar\nbaz\n"
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
   FOO
   BAR
   BAZ
 
 Tests for the fix extension's behavior around non-trivial history topologies.
 Looks for correct incremental fixing and reproduction of parent/child
 relationships. We indicate fixed file content by uppercasing it.
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > fix =
   > [fix]
-  > uppercase-whole-file:command=$PYTHON $UPPERCASEPY
+  > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY
   > uppercase-whole-file:fileset=set:**
   > EOF
 
 This tests the only behavior that should really be affected by obsolescence, so
 we'll test it with evolution off and on. This only changes the revision
 numbers, if all is well.
 
 #testcases obsstore-off obsstore-on
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -17,42 +17,42 @@ approximates the behavior of code format
   >     lines.update(range(int(first), int(last) + 1))
   > for i, line in enumerate(sys.stdin.readlines()):
   >   if i + 1 in lines:
   >     sys.stdout.write(line.upper())
   >   else:
   >     sys.stdout.write(line)
   > EOF
   $ TESTLINES="foo\nbar\nbaz\nqux\n"
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY
   foo
   bar
   baz
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY all
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY all
   FOO
   BAR
   BAZ
   QUX
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-1
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-1
   FOO
   bar
   baz
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 1-2
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 1-2
   FOO
   BAR
   baz
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-3
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-3
   foo
   BAR
   BAZ
   qux
-  $ printf $TESTLINES | $PYTHON $UPPERCASEPY 2-2 4-4
+  $ printf $TESTLINES | "$PYTHON" $UPPERCASEPY 2-2 4-4
   foo
   BAR
   baz
   QUX
 
 Set up the config with two simple fixers: one that fixes specific line ranges,
 and one that always fixes the whole file. They both "fix" files by converting
 letters to uppercase. They use different file extensions, so each test case can
@@ -60,19 +60,19 @@ choose which behavior to use by naming f
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > fix =
   > [experimental]
   > evolution.createmarkers=True
   > evolution.allowunstable=True
   > [fix]
-  > uppercase-whole-file:command=$PYTHON $UPPERCASEPY all
+  > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
   > uppercase-whole-file:fileset=set:**.whole
-  > uppercase-changed-lines:command=$PYTHON $UPPERCASEPY
+  > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
   > uppercase-changed-lines:linerange={first}-{last}
   > uppercase-changed-lines:fileset=set:**.changed
   > EOF
 
 Help text for fix.
 
   $ hg help fix
   hg fix [OPTION]... [FILE]...
--- a/tests/test-gendoc.t
+++ b/tests/test-gendoc.t
@@ -3,17 +3,17 @@
 
 Test document extraction
 
   $ HGENCODING=UTF-8
   $ export HGENCODING
   $ { echo C; ls "$TESTDIR/../i18n"/*.po | sort; } | while read PO; do
   >     LOCALE=`basename "$PO" .po`
   >     echo "% extracting documentation from $LOCALE"
-  >     LANGUAGE=$LOCALE $PYTHON "$TESTDIR/../doc/gendoc.py" >> gendoc-$LOCALE.txt 2> /dev/null || exit
+  >     LANGUAGE=$LOCALE "$PYTHON" "$TESTDIR/../doc/gendoc.py" >> gendoc-$LOCALE.txt 2> /dev/null || exit
   > 
   >     if [ $LOCALE != C ]; then
   >         if [ ! -f $TESTDIR/test-gendoc-$LOCALE.t ]; then
   >             echo missing test-gendoc-$LOCALE.t
   >         fi
   >         cmp -s gendoc-C.txt gendoc-$LOCALE.txt && echo "** NOTHING TRANSLATED ($LOCALE) **"
   >     fi
   > done; true
--- a/tests/test-glog-beautifygraph.t
+++ b/tests/test-glog-beautifygraph.t
@@ -1804,17 +1804,17 @@ Test multiple --include/--exclude/paths
       (string 'x:b')
       (string 'x:e')))
   <filteredset
     <spanset- 0:5>,
     <matchfiles patterns=['a', 'e'], include=['a', 'e'] exclude=['b', 'e'], default='relpath', rev=2147483647>>
 
 Test glob expansion of pats
 
-  $ expandglobs=`$PYTHON -c "import mercurial.util; \
+  $ expandglobs=`"$PYTHON" -c "import mercurial.util; \
   >   print(mercurial.util.expandglobs and 'true' or 'false')"`
   $ if [ $expandglobs = "true" ]; then
   >    testlog 'a*';
   > else
   >    testlog a*;
   > fi;
   []
   (func
--- a/tests/test-glog.t
+++ b/tests/test-glog.t
@@ -1654,17 +1654,17 @@ Test multiple --include/--exclude/paths
       (string 'x:b')
       (string 'x:e')))
   <filteredset
     <spanset- 0:5>,
     <matchfiles patterns=['a', 'e'], include=['a', 'e'] exclude=['b', 'e'], default='relpath', rev=2147483647>>
 
 Test glob expansion of pats
 
-  $ expandglobs=`$PYTHON -c "import mercurial.util; \
+  $ expandglobs=`"$PYTHON" -c "import mercurial.util; \
   >   print(mercurial.util.expandglobs and 'true' or 'false')"`
   $ if [ $expandglobs = "true" ]; then
   >    testlog 'a*';
   > else
   >    testlog a*;
   > fi;
   []
   (func
--- a/tests/test-grep.t
+++ b/tests/test-grep.t
@@ -295,17 +295,17 @@ test substring match: '^' should only ma
 
   $ hg grep -r tip:0 '^.' --config extensions.color= --color debug
   [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lack
   [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|o]range
   [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lue
 
 match in last "line" without newline
 
-  $ $PYTHON -c 'fp = open("noeol", "wb"); fp.write(b"no infinite loop"); fp.close();'
+  $ "$PYTHON" -c 'fp = open("noeol", "wb"); fp.write(b"no infinite loop"); fp.close();'
   $ hg ci -Amnoeol
   adding noeol
   $ hg grep -r tip:0 loop
   noeol:4:no infinite loop
 
   $ cd ..
 
 Issue685: traceback in grep -r after rename
--- a/tests/test-hardlinks.t
+++ b/tests/test-hardlinks.t
@@ -6,31 +6,31 @@
   > from mercurial import util
   > for f in sorted(sys.stdin.readlines()):
   >     f = f[:-1]
   >     print(util.nlinks(f), f)
   > EOF
 
   $ nlinksdir()
   > {
-  >     find "$@" -type f | $PYTHON $TESTTMP/nlinks.py
+  >     find "$@" -type f | "$PYTHON" $TESTTMP/nlinks.py
   > }
 
 Some implementations of cp can't create hardlinks (replaces 'cp -al' on Linux):
 
   $ cat > linkcp.py <<EOF
   > from __future__ import absolute_import
   > import sys
   > from mercurial import util
   > util.copyfiles(sys.argv[1], sys.argv[2], hardlink=True)
   > EOF
 
   $ linkcp()
   > {
-  >     $PYTHON $TESTTMP/linkcp.py $1 $2
+  >     "$PYTHON" $TESTTMP/linkcp.py $1 $2
   > }
 
 Prepare repo r1:
 
   $ hg init r1
   $ cd r1
 
   $ echo c1 > f1
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -1767,17 +1767,17 @@ as the second or later byte of multi-byt
 
 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
 replacement makes message meaningless.
 
 This tests that section lookup by translated string isn't broken by
 such str.lower().
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > def escape(s):
   >     return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
   > # translation of "record" in ja_JP.cp932
   > upper = "\x8bL\x98^"
   > # str.lower()-ed section name should be treated as different one
   > lower = "\x8bl\x98^"
   > with open('ambiguous.py', 'w') as fp:
   >     fp.write("""# ambiguous section names in ja_JP.cp932
@@ -1801,27 +1801,27 @@ such str.lower().
   > """ % (escape(upper), escape(lower)))
   > EOF
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > ambiguous = ./ambiguous.py
   > EOF
 
-  $ $PYTHON <<EOF | sh
+  $ "$PYTHON" <<EOF | sh
   > upper = "\x8bL\x98^"
   > print("hg --encoding cp932 help -e ambiguous.%s" % upper)
   > EOF
   \x8bL\x98^ (esc)
   ----
   
   Upper name should show only this message
   
 
-  $ $PYTHON <<EOF | sh
+  $ "$PYTHON" <<EOF | sh
   > lower = "\x8bl\x98^"
   > print("hg --encoding cp932 help -e ambiguous.%s" % lower)
   > EOF
   \x8bl\x98^ (esc)
   ----
   
   Lower name should show only this message
   
@@ -2021,17 +2021,17 @@ Compression engines listed in `hg help b
         An algorithm that produces smaller bundles than "gzip".
         This engine will likely produce smaller bundles than "gzip" but will be
       "gzip"
         better compression than "gzip". It also frequently yields better (?)
 
 Test usage of section marks in help documents
 
   $ cd "$TESTDIR"/../doc
-  $ $PYTHON check-seclevel.py
+  $ "$PYTHON" check-seclevel.py
   $ cd $TESTTMP
 
 #if serve
 
 Test the help pages in hgweb.
 
 Dish up an empty repo; serve it cold.
 
--- a/tests/test-hghave.t
+++ b/tests/test-hghave.t
@@ -17,17 +17,17 @@ Testing hghave extensibility for third p
 
   $ cat > test-hghaveaddon.t <<EOF
   > #require custom
   >   $ echo foo
   >   foo
   > EOF
   $ ( \
   > testrepohgenv; \
-  > $PYTHON $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE test-hghaveaddon.t \
+  > "$PYTHON" $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE test-hghaveaddon.t \
   > )
   .
   # Ran 1 tests, 0 skipped, 0 failed.
 
 (invocation via command line)
 
   $ unset TESTDIR
   $ hghave custom
--- a/tests/test-hgignore.t
+++ b/tests/test-hgignore.t
@@ -14,17 +14,17 @@ Issue562: .hgignore requires newline at 
   > f = open(".hgignore", "w")
   > f.write("ignore\n")
   > f.write("foo\n")
   > # No EOL here
   > f.write("bar")
   > f.close()
   > EOF
 
-  $ $PYTHON makeignore.py
+  $ "$PYTHON" makeignore.py
 
 Should display baz only:
 
   $ hg status
   ? baz
 
   $ rm foo bar baz .hgignore makeignore.py
 
--- a/tests/test-hgrc.t
+++ b/tests/test-hgrc.t
@@ -53,17 +53,17 @@ issue1829: wrong indentation
 
   $ echo '[foo]' > $HGRC
   $ echo '  x = y' >> $HGRC
   $ hg version
   hg: parse error at $TESTTMP/hgrc:2:   x = y
   unexpected leading whitespace
   [255]
 
-  $ $PYTHON -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n  de\n fg \nbaz = bif cb \n')" \
+  $ "$PYTHON" -c "from __future__ import print_function; print('[foo]\nbar = a\n b\n c \n  de\n fg \nbaz = bif cb \n')" \
   > > $HGRC
   $ hg showconfig foo
   foo.bar=a\nb\nc\nde\nfg
   foo.baz=bif cb
 
   $ FAKEPATH=/path/to/nowhere
   $ export FAKEPATH
   $ echo '%include $FAKEPATH/no-such-file' > $HGRC
--- a/tests/test-hgweb-commands.t
+++ b/tests/test-hgweb-commands.t
@@ -2277,69 +2277,69 @@ bookmarks view doesn't choke on bookmark
   > from mercurial.hgweb import hgweb
   > from mercurial.hgweb import wsgicgi
   > app = hgweb(b'.', b'test')
   > wsgicgi.launch(app)
   > HGWEB
   $ . "$TESTDIR/cgienv"
   $ PATH_INFO=/bookmarks; export PATH_INFO
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi | grep -v ETag:
+  $ "$PYTHON" hgweb.cgi | grep -v ETag:
   Status: 200 Script output follows\r (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
   \r (esc)
 
 listbookmarks hides secret bookmarks
 
   $ PATH_INFO=/; export PATH_INFO
   $ QUERY_STRING='cmd=listkeys&namespace=bookmarks'
-  $ $PYTHON hgweb.cgi
+  $ "$PYTHON" hgweb.cgi
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 0\r (esc)
   \r (esc)
 
 search works with filtering
 
   $ PATH_INFO=/log; export PATH_INFO
   $ QUERY_STRING='rev=babar'
-  $ $PYTHON hgweb.cgi > search
+  $ "$PYTHON" hgweb.cgi > search
   $ grep Status search
   Status: 200 Script output follows\r (esc)
 
 summary works with filtering (issue3810)
 
   $ PATH_INFO=/summary; export PATH_INFO
   $ QUERY_STRING='style=monoblue'; export QUERY_STRING
-  $ $PYTHON hgweb.cgi > summary.out
+  $ "$PYTHON" hgweb.cgi > summary.out
   $ grep "^Status" summary.out
   Status: 200 Script output follows\r (esc)
 
 proper status for filtered revision
 
 
 (missing rev)
 
   $ PATH_INFO=/rev/5; export PATH_INFO
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi #> search
+  $ "$PYTHON" hgweb.cgi #> search
   Status: 404 Not Found\r (esc)
   ETag: W/"*"\r (glob) (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
   \r (esc)
   
   error: filtered revision '5' (not in 'served' subset)
 
 
 
 (filtered rev)
 
   $ PATH_INFO=/rev/4; export PATH_INFO
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi #> search
+  $ "$PYTHON" hgweb.cgi #> search
   Status: 404 Not Found\r (esc)
   ETag: W/"*"\r (glob) (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
   \r (esc)
   
   error: filtered revision '4' (not in 'served' subset)
 
 filtered '0' changeset
@@ -2357,21 +2357,21 @@ filtered '0' changeset
   grafting 2:ab4f1438558b "2"
   grafting 3:ada793dcc118 "3"
   grafting 4:b60a39a85a01 "4" (secret)
   grafting 5:aed2d9c1d0e7 "5"
 (turning the initial root secret (filtered))
   $ hg phase --force --secret 0
   $ PATH_INFO=/graph/; export PATH_INFO
   $ QUERY_STRING=''
-  $ $PYTHON hgweb.cgi | grep Status
+  $ "$PYTHON" hgweb.cgi | grep Status
   Status: 200 Script output follows\r (esc)
 (check rendered revision)
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi | grep -v ETag
+  $ "$PYTHON" hgweb.cgi | grep -v ETag
   Status: 200 Script output follows\r (esc)
   Content-Type: text/plain; charset=ascii\r (esc)
   \r (esc)
   
   # HG graph
   # Node ID 1d9b947fef1fbb382a95c11a8f5a67e9a10b5026
   # Rows shown 7
   
--- a/tests/test-hgweb-json.t
+++ b/tests/test-hgweb-json.t
@@ -2191,17 +2191,17 @@ Error page shouldn't crash
   {
     "error": "unknown revision 'deadbeef'"
   }
   [1]
 
 Commit message with Japanese Kanji 'Noh', which ends with '\x5c'
 
   $ echo foo >> da/foo
-  $ HGENCODING=cp932 hg ci -m `$PYTHON -c 'print("\x94\x5c")'`
+  $ HGENCODING=cp932 hg ci -m `"$PYTHON" -c 'print("\x94\x5c")'`
 
 Commit message with null character
 
   $ echo foo >> da/foo
   >>> open('msg', 'wb').write('commit with null character: \0\n')
   $ hg ci -l msg
   $ rm msg
 
--- a/tests/test-hgweb-no-path-info.t
+++ b/tests/test-hgweb-no-path-info.t
@@ -65,17 +65,17 @@ should be used from d74fc8dec2b4 onward 
   > output = stringio()
   > env['QUERY_STRING'] = 'style=atom'
   > process(hgweb(b'.', name=b'repo'))
   > 
   > output = stringio()
   > env['QUERY_STRING'] = 'style=raw'
   > process(hgwebdir({b'repo': b'.'}))
   > EOF
-  $ $PYTHON request.py
+  $ "$PYTHON" request.py
   ---- STATUS
   200 Script output follows
   ---- HEADERS
   [('Content-Type', 'application/atom+xml; charset=ascii')]
   ---- DATA
   <?xml version="1.0" encoding="ascii"?>
   <feed xmlns="http://www.w3.org/2005/Atom">
    <!-- Changelog -->
--- a/tests/test-hgweb-no-request-uri.t
+++ b/tests/test-hgweb-no-request-uri.t
@@ -76,17 +76,17 @@ should be used from d74fc8dec2b4 onward 
   > env['QUERY_STRING'] = 'style=raw'
   > process(hgwebdir({b'repo': b'.'}))
   > 
   > output = stringio()
   > env['PATH_INFO'] = '/repo/file/tip/'
   > env['QUERY_STRING'] = 'style=raw'
   > process(hgwebdir({b'repo': b'.'}))
   > EOF
-  $ $PYTHON request.py
+  $ "$PYTHON" request.py
   ---- STATUS
   200 Script output follows
   ---- HEADERS
   [('Content-Type', 'application/atom+xml; charset=ascii')]
   ---- DATA
   <?xml version="1.0" encoding="ascii"?>
   <feed xmlns="http://www.w3.org/2005/Atom">
    <!-- Changelog -->
--- a/tests/test-hgweb-non-interactive.t
+++ b/tests/test-hgweb-non-interactive.t
@@ -71,17 +71,17 @@ by the WSGI standard and strictly implem
   > print('---- ERRORS')
   > print(errors.getvalue())
   > print('---- OS.ENVIRON wsgi variables')
   > print(sorted([x for x in os.environ if x.startswith('wsgi')]))
   > print('---- request.ENVIRON wsgi variables')
   > with i._obtainrepo() as repo:
   >     print(sorted([x for x in repo.ui.environ if x.startswith(b'wsgi')]))
   > EOF
-  $ $PYTHON request.py
+  $ "$PYTHON" request.py
   ---- STATUS
   200 Script output follows
   ---- HEADERS
   [('Content-Type', 'text/html; charset=ascii')]
   ---- DATA
   ---- ERRORS
   
   ---- OS.ENVIRON wsgi variables
--- a/tests/test-hgweb.t
+++ b/tests/test-hgweb.t
@@ -324,17 +324,17 @@ try bad style
 stop and restart
 
   $ killdaemons.py
   $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log
   $ cat hg.pid >> $DAEMON_PIDS
 
 Test the access/error files are opened in append mode
 
-  $ $PYTHON -c "from __future__ import print_function; print(len(open('access.log', 'rb').readlines()), 'log lines written')"
+  $ "$PYTHON" -c "from __future__ import print_function; print(len(open('access.log', 'rb').readlines()), 'log lines written')"
   14 log lines written
 
 static file
 
   $ get-with-headers.py --twice localhost:$HGPORT 'static/style-gitweb.css' - date etag server
   200 Script output follows
   content-length: 9074
   content-type: text/css
--- a/tests/test-highlight.t
+++ b/tests/test-highlight.t
@@ -942,17 +942,17 @@ test that fileset in highlightfiles work
   <span id="l11">    def sieve(ns):</span><a href="#l11"></a>
 
 errors encountered
 
   $ cat errors.log
   $ cd ..
   $ hg init eucjp
   $ cd eucjp
-  $ $PYTHON -c 'print("\265\376")' >> eucjp.txt  # Japanese kanji "Kyo"
+  $ "$PYTHON" -c 'print("\265\376")' >> eucjp.txt  # Japanese kanji "Kyo"
   $ hg ci -Ama
   adding eucjp.txt
   $ hgserveget () {
   >     killdaemons.py
   >     echo % HGENCODING="$1" hg serve
   >     HGENCODING="$1" hg serve -p $HGPORT -d -n test --pid-file=hg.pid -E errors.log
   >     cat hg.pid >> $DAEMON_PIDS
   > 
--- a/tests/test-histedit-arguments.t
+++ b/tests/test-histedit-arguments.t
@@ -274,17 +274,17 @@ short hash. This tests issue3893.
   created new head
   $ hg histedit -r 'heads(all())'
   abort: The specified revisions must have exactly one common root
   [255]
 
 Test that trimming description using multi-byte characters
 --------------------------------------------------------------------
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > fp = open('logfile', 'wb')
   > fp.write(b'12345678901234567890123456789012345678901234567890' +
   >          b'12345') # there are 5 more columns for 80 columns
   > 
   > # 2 x 4 = 8 columns, but 3 x 4 = 12 bytes
   > fp.write(u'\u3042\u3044\u3046\u3048'.encode('utf-8'))
   > 
   > fp.close()
--- a/tests/test-i18n.t
+++ b/tests/test-i18n.t
@@ -40,18 +40,18 @@ Test keyword search in translated help t
    update Aktualisiert das Arbeitsverzeichnis (oder wechselt die Version)
 
 #endif
 
 Check Mercurial specific translation problems in each *.po files, and
 tool itself by doctest
 
   $ cd "$TESTDIR"/../i18n
-  $ $PYTHON check-translation.py *.po
-  $ $PYTHON check-translation.py --doctest
+  $ "$PYTHON" check-translation.py *.po
+  $ "$PYTHON" check-translation.py --doctest
   $ cd $TESTTMP
 
 #if gettext
 
 Check i18n cache isn't reused after encoding change:
 
   $ cat > $TESTTMP/encodingchange.py << EOF
   > from mercurial.i18n import _
--- a/tests/test-impexp-branch.t
+++ b/tests/test-impexp-branch.t
@@ -27,22 +27,22 @@
   (branches are permanent and global, did you want a bookmark?)
   $ echo "Rev  2" >rev
   $ hg commit -m "With branch."
 
   $ hg export 0 > ../r0.patch
   $ hg export 1 > ../r1.patch
   $ cd ..
 
-  $ if $PYTHON findbranch.py < r0.patch; then
+  $ if "$PYTHON" findbranch.py < r0.patch; then
   >     echo "Export of default branch revision has Branch header" 1>&2
   >     exit 1
   > fi
 
-  $ if $PYTHON findbranch.py < r1.patch; then
+  $ if "$PYTHON" findbranch.py < r1.patch; then
   >     :  # Do nothing
   > else
   >     echo "Export of branch revision is missing Branch header" 1>&2
   >     exit 1
   > fi
 
 Make sure import still works with branch information in patches.
 
--- a/tests/test-import-bypass.t
+++ b/tests/test-import-bypass.t
@@ -222,17 +222,17 @@ the commit message, regardless of '--edi
   HG: changed a
   abort: empty commit message
   [255]
 
 Test patch.eol is handled
 (this also tests that editor is not invoked for '--bypass', if the
 commit message is explicitly specified, regardless of '--edit')
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\r\n")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\r\n")'
   $ hg ci -m makeacrlf
   $ HGEDITOR=cat hg import -m 'should fail because of eol' --edit --bypass ../test.diff
   applying ../test.diff
   patching file a
   Hunk #1 FAILED at 0
   abort: patch failed to apply
   [255]
   $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
--- a/tests/test-import-context.t
+++ b/tests/test-import-context.t
@@ -21,20 +21,20 @@ Test applying context diffs
   > import sys
   > sys.stdout.write(repr(open(sys.argv[1], 'rb').read()) + '\n')
   > EOF
 
 Initialize the test repository
 
   $ hg init repo
   $ cd repo
-  $ $PYTHON ../writepatterns.py a 0 5A 1B 5C 1D
-  $ $PYTHON ../writepatterns.py b 1 1A 1B
-  $ $PYTHON ../writepatterns.py c 1 5A
-  $ $PYTHON ../writepatterns.py d 1 5A 1B
+  $ "$PYTHON" ../writepatterns.py a 0 5A 1B 5C 1D
+  $ "$PYTHON" ../writepatterns.py b 1 1A 1B
+  $ "$PYTHON" ../writepatterns.py c 1 5A
+  $ "$PYTHON" ../writepatterns.py d 1 5A 1B
   $ hg add
   adding a
   adding b
   adding c
   adding d
   $ hg ci -m addfiles
 
 Add file, missing a last end of line
@@ -109,18 +109,18 @@ Add file, missing a last end of line
   M a
   M c
   M d
   A newnoeol
   R b
 
 What's in a
 
-  $ $PYTHON ../cat.py a
+  $ "$PYTHON" ../cat.py a
   'A\nA\nA\nA\nA\nE\nC\nC\nC\nC\nC\nF\nF\n'
-  $ $PYTHON ../cat.py newnoeol
+  $ "$PYTHON" ../cat.py newnoeol
   'a\nb'
-  $ $PYTHON ../cat.py c
+  $ "$PYTHON" ../cat.py c
   'A\nA\nA\nA\nA\nB\nB\n'
-  $ $PYTHON ../cat.py d
+  $ "$PYTHON" ../cat.py d
   'A\nA\nA\nA\n'
 
   $ cd ..
--- a/tests/test-import-eol.t
+++ b/tests/test-import-eol.t
@@ -24,24 +24,24 @@
 
   $ hg init repo
   $ cd repo
   $ echo '\.diff' > .hgignore
 
 
 Test different --eol values
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\nbbb\ncc\n\nd\ne")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\nbbb\ncc\n\nd\ne")'
   $ hg ci -Am adda
   adding .hgignore
   adding a
-  $ $PYTHON ../makepatch.py empty:lf eol.diff
-  $ $PYTHON ../makepatch.py empty:crlf eol-empty-crlf.diff
-  $ $PYTHON ../makepatch.py empty:stripped-lf eol-empty-stripped-lf.diff
-  $ $PYTHON ../makepatch.py empty:stripped-crlf eol-empty-stripped-crlf.diff
+  $ "$PYTHON" ../makepatch.py empty:lf eol.diff
+  $ "$PYTHON" ../makepatch.py empty:crlf eol-empty-crlf.diff
+  $ "$PYTHON" ../makepatch.py empty:stripped-lf eol-empty-stripped-lf.diff
+  $ "$PYTHON" ../makepatch.py empty:stripped-crlf eol-empty-stripped-crlf.diff
 
 invalid eol
 
   $ hg --config patch.eol='LFCR' import eol.diff
   applying eol.diff
   abort: unsupported line endings type: LFCR
   [255]
   $ hg revert -a
@@ -111,37 +111,37 @@ auto EOL on LF file
   
   d
   e (no-eol)
   $ hg st
 
 
 auto EOL on CRLF file
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\r\nbbb\r\ncc\r\n\r\nd\r\ne")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\r\nbbb\r\ncc\r\n\r\nd\r\ne")'
   $ hg commit -m 'switch EOLs in a'
   $ hg --traceback --config patch.eol='auto' import eol.diff
   applying eol.diff
   $ cat a
   a\r (esc)
   yyyy\r (esc)
   cc\r (esc)
   \r (esc)
   d\r (esc)
   e (no-eol)
   $ hg st
 
 
 auto EOL on new file or source without any EOL
 
-  $ $PYTHON -c 'open("noeol", "wb").write(b"noeol")'
+  $ "$PYTHON" -c 'open("noeol", "wb").write(b"noeol")'
   $ hg add noeol
   $ hg commit -m 'add noeol'
-  $ $PYTHON -c 'open("noeol", "wb").write(b"noeol\r\nnoeol\n")'
-  $ $PYTHON -c 'open("neweol", "wb").write(b"neweol\nneweol\r\n")'
+  $ "$PYTHON" -c 'open("noeol", "wb").write(b"noeol\r\nnoeol\n")'
+  $ "$PYTHON" -c 'open("neweol", "wb").write(b"neweol\nneweol\r\n")'
   $ hg add neweol
   $ hg diff --git > noeol.diff
   $ hg revert --no-backup noeol neweol
   $ rm neweol
   $ hg --traceback --config patch.eol='auto' import -m noeol noeol.diff
   applying noeol.diff
   $ cat noeol
   noeol\r (esc)
@@ -149,20 +149,20 @@ auto EOL on new file or source without a
   $ cat neweol
   neweol
   neweol\r (esc)
   $ hg st
 
 
 Test --eol and binary patches
 
-  $ $PYTHON -c 'open("b", "wb").write(b"a\x00\nb\r\nd")'
+  $ "$PYTHON" -c 'open("b", "wb").write(b"a\x00\nb\r\nd")'
   $ hg ci -Am addb
   adding b
-  $ $PYTHON -c 'open("b", "wb").write(b"a\x00\nc\r\nd")'
+  $ "$PYTHON" -c 'open("b", "wb").write(b"a\x00\nc\r\nd")'
   $ hg diff --git > bin.diff
   $ hg revert --no-backup b
 
 binary patch with --eol
 
   $ hg import --config patch.eol='CRLF' -m changeb bin.diff
   applying bin.diff
   $ cat b
--- a/tests/test-import.t
+++ b/tests/test-import.t
@@ -300,17 +300,17 @@ plain diff in email, subject, message bo
   $ hg clone -r0 a b
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
   new changesets 80971e65b431
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON mkmsg.py diffed-tip.patch msg.patch
+  $ "$PYTHON" mkmsg.py diffed-tip.patch msg.patch
   $ hg --cwd b import ../msg.patch
   applying ../msg.patch
   $ hg --cwd b tip | grep email
   user:        email patcher
   summary:     email patch
   $ rm -r b
 
 
@@ -366,17 +366,17 @@ hg export in email, should use patch hea
   $ hg clone -r0 a b
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
   new changesets 80971e65b431
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON mkmsg.py exported-tip.patch msg.patch
+  $ "$PYTHON" mkmsg.py exported-tip.patch msg.patch
   $ cat msg.patch | hg --cwd b import -
   applying patch from stdin
   $ hg --cwd b tip | grep second
   summary:     second change
   $ rm -r b
 
 
 subject: duplicate detection, removal of [PATCH]
@@ -398,17 +398,17 @@ plain diff in email, [PATCH] subject, me
   $ hg clone -r0 a b
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
   new changesets 80971e65b431
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ $PYTHON mkmsg2.py diffed-tip.patch msg.patch
+  $ "$PYTHON" mkmsg2.py diffed-tip.patch msg.patch
   $ cat msg.patch | hg --cwd b import -
   applying patch from stdin
   $ hg --cwd b tip --template '{desc}\n'
   email patch
   
   next line
   $ rm -r b
 
@@ -860,17 +860,17 @@ Test hunk touching empty files (issue906
   $ cd ..
 
 
 Test importing a patch ending with a binary file removal
 
   $ hg init binaryremoval
   $ cd binaryremoval
   $ echo a > a
-  $ $PYTHON -c "open('b', 'wb').write(b'a\x00b')"
+  $ "$PYTHON" -c "open('b', 'wb').write(b'a\x00b')"
   $ hg ci -Am addall
   adding a
   adding b
   $ hg rm a
   $ hg rm b
   $ hg st
   R a
   R b
--- a/tests/test-imports-checker.t
+++ b/tests/test-imports-checker.t
@@ -3,17 +3,17 @@
   $ . "$TESTDIR/helpers-testrepo.sh"
   $ testrepohgenv
   $ import_checker="$TESTDIR"/../contrib/import-checker.py
 
 Run the doctests from the import checker, and make sure
 it's working correctly.
   $ TERM=dumb
   $ export TERM
-  $ $PYTHON -m doctest $import_checker
+  $ "$PYTHON" -m doctest $import_checker
 
 Run additional tests for the import checker
 
   $ mkdir testpackage
   $ touch testpackage/__init__.py
 
   $ cat > testpackage/multiple.py << EOF
   > from __future__ import absolute_import
@@ -131,17 +131,17 @@ Run additional tests for the import chec
   $ mkdir email
   $ touch email/__init__.py
   $ touch email/errors.py
   $ cat > email/utils.py << EOF
   > from __future__ import absolute_import
   > from . import errors
   > EOF
 
-  $ $PYTHON "$import_checker" testpackage*/*.py testpackage/subpackage/*.py \
+  $ "$PYTHON" "$import_checker" testpackage*/*.py testpackage/subpackage/*.py \
   >   email/*.py
   testpackage/importalias.py:2: ui module must be "as" aliased to uimod
   testpackage/importfromalias.py:2: ui from testpackage must be "as" aliased to uimod
   testpackage/importfromrelative.py:2: import should be relative: testpackage.unsorted
   testpackage/importfromrelative.py:2: direct symbol import foo from testpackage.unsorted
   testpackage/importsymbolfromsub.py:2: direct symbol import nonmodule from testpackage.subpackage
   testpackage/latesymbolimport.py:3: symbol import follows non-symbol import: mercurial.node
   testpackage/multiple.py:2: multiple imported names: os, sys
--- a/tests/test-inherit-mode.t
+++ b/tests/test-inherit-mode.t
@@ -43,33 +43,33 @@ just in case somebody has a strange $TMP
   $ cd repo
 
   $ chmod 0770 .hg/store
 
 before commit
 store can be written by the group, other files cannot
 store is setgid
 
-  $ $PYTHON ../printmodes.py .
+  $ "$PYTHON" ../printmodes.py .
   00700 ./.hg/
   00600 ./.hg/00changelog.i
   00600 ./.hg/requires
   00770 ./.hg/store/
 
   $ mkdir dir
   $ touch foo dir/bar
   $ hg ci -qAm 'add files'
 
 after commit
 working dir files can only be written by the owner
 files created in .hg can be written by the group
 (in particular, store/**, dirstate, branch cache file, undo files)
 new directories are setgid
 
-  $ $PYTHON ../printmodes.py .
+  $ "$PYTHON" ../printmodes.py .
   00700 ./.hg/
   00600 ./.hg/00changelog.i
   00770 ./.hg/cache/
   00660 ./.hg/cache/branch2-served
   00660 ./.hg/cache/manifestfulltextcache (reporevlogstore !)
   00660 ./.hg/cache/rbc-names-v1
   00660 ./.hg/cache/rbc-revs-v1
   00660 ./.hg/dirstate
@@ -104,29 +104,29 @@ new directories are setgid
   00600 ./foo
 
   $ umask 007
   $ hg init ../push
 
 before push
 group can write everything
 
-  $ $PYTHON ../printmodes.py ../push
+  $ "$PYTHON" ../printmodes.py ../push
   00770 ../push/.hg/
   00660 ../push/.hg/00changelog.i
   00660 ../push/.hg/requires
   00770 ../push/.hg/store/
 
   $ umask 077
   $ hg -q push ../push
 
 after push
 group can still write everything
 
-  $ $PYTHON ../printmodes.py ../push
+  $ "$PYTHON" ../printmodes.py ../push
   00770 ../push/.hg/
   00660 ../push/.hg/00changelog.i
   00770 ../push/.hg/cache/
   00660 ../push/.hg/cache/branch2-base
   00660 ../push/.hg/dirstate
   00660 ../push/.hg/requires
   00770 ../push/.hg/store/
   00660 ../push/.hg/store/00changelog.i
@@ -158,16 +158,16 @@ just check that directories have the sam
   $ cd ..
   $ hg init setgid
   $ cd setgid
   $ chmod g+rwx .hg/store
   $ chmod g+s .hg/store 2> /dev/null || true
   $ mkdir dir
   $ touch dir/file
   $ hg ci -qAm 'add dir/file'
-  $ storemode=`$PYTHON ../mode.py .hg/store`
-  $ dirmode=`$PYTHON ../mode.py .hg/store/data/dir`
+  $ storemode=`"$PYTHON" ../mode.py .hg/store`
+  $ dirmode=`"$PYTHON" ../mode.py .hg/store/data/dir`
   $ if [ "$storemode" != "$dirmode" ]; then
   >  echo "$storemode != $dirmode"
   > fi
   $ cd ..
 
   $ cd .. # g-s dir
--- a/tests/test-install.t
+++ b/tests/test-install.t
@@ -200,43 +200,43 @@ not found (this is intentionally using b
   > for f in sorted(set(tracked) - set(installed)):
   >     print('  %s' % f)
   > 
   > print('Not tracked:')
   > for f in sorted(set(installed) - set(tracked)):
   >     print('  %s' % f)
   > EOF
 
-  $ ( testrepohgenv; $PYTHON wixxml.py help )
+  $ ( testrepohgenv; "$PYTHON" wixxml.py help )
   Not installed:
     help/common.txt
     help/hg-ssh.8.txt
     help/hg.1.txt
     help/hgignore.5.txt
     help/hgrc.5.txt
   Not tracked:
 
-  $ ( testrepohgenv; $PYTHON wixxml.py templates )
+  $ ( testrepohgenv; "$PYTHON" wixxml.py templates )
   Not installed:
   Not tracked:
 
 #endif
 
 #if virtualenv
 
 Verify that Mercurial is installable with pip. Note that this MUST be
 the last test in this file, because we do some nasty things to the
 shell environment in order to make the virtualenv work reliably.
 
   $ cd $TESTTMP
 Note: --no-site-packages is deprecated, but some places have an
 ancient virtualenv from their linux distro or similar and it's not yet
 the default for them.
   $ unset PYTHONPATH
-  $ $PYTHON -m virtualenv --no-site-packages --never-download installenv >> pip.log
+  $ "$PYTHON" -m virtualenv --no-site-packages --never-download installenv >> pip.log
 Note: we use this weird path to run pip and hg to avoid platform differences,
 since it's bin on most platforms but Scripts on Windows.
   $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log
   $ ./installenv/*/hg debuginstall || cat pip.log
   checking encoding (ascii)...
   checking Python executable (*) (glob)
   checking Python version (2.*) (glob)
   checking Python lib (*)... (glob)
--- a/tests/test-issue4074.t
+++ b/tests/test-issue4074.t
@@ -11,19 +11,19 @@ A script to generate nasty diff worst-ca
   >     print(hex(x))
   > EOF
 
   $ hg init a
   $ cd a
 
 Check in a big file:
 
-  $ $PYTHON ../s.py > a
+  $ "$PYTHON" ../s.py > a
   $ hg ci -qAm0
 
 Modify it:
 
-  $ $PYTHON ../s.py > a
+  $ "$PYTHON" ../s.py > a
 
 Time a check-in, should never take more than 10 seconds user time:
 
   $ hg ci --time -m1
   time: real .* secs .user [0-9][.].* sys .* (re)
--- a/tests/test-largefiles-misc.t
+++ b/tests/test-largefiles-misc.t
@@ -1090,32 +1090,32 @@ largefiles (issue4547)
   $ hg -R subrepo-root revert --all
   reverting subrepo-root/.hglf/large
   reverting subrepo no-largefiles
   reverting subrepo-root/no-largefiles/normal1
 
 Move (and then undo) a directory move with only largefiles.
 
   $ cd subrepo-root
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir/
   .hglf/dir/subdir/large.bin
   .hglf/large
   dir/
   dir/subdir/
   dir/subdir/large.bin
   large
   large.orig
 
   $ hg mv dir/subdir dir/subdir2
   moving .hglf/dir/subdir/large.bin to .hglf/dir/subdir2/large.bin
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir2/
   .hglf/dir/subdir2/large.bin
   .hglf/large
   dir/
   dir/subdir2/
   dir/subdir2/large.bin
@@ -1145,17 +1145,17 @@ Move (and then undo) a directory move wi
 
 The content of the forgotten file shouldn't be clobbered
 
   $ cat dir/subdir2/large.bin
   modified
 
 The standin for subdir2 should be deleted, not just dropped
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir/
   .hglf/dir/subdir/large.bin
   .hglf/large
   dir/
   dir/subdir/
   dir/subdir/large.bin
@@ -1172,17 +1172,17 @@ existed under .hglf/.
   moving .hglf/dir/subdir/large.bin to .hglf/dir/subdir2/large.bin
 
   $ hg status -C
   A dir/subdir2/large.bin
     dir/subdir/large.bin
   R dir/subdir/large.bin
   ? large.orig
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir2/
   .hglf/dir/subdir2/large.bin
   .hglf/large
   dir/
   dir/subdir2/
   dir/subdir2/large.bin
@@ -1197,17 +1197,17 @@ Start from scratch, and rename something
   $ hg mv dir/subdir dir2/subdir
   moving .hglf/dir/subdir/large.bin to .hglf/dir2/subdir/large.bin
 
   $ hg status -C
   A dir2/subdir/large.bin
     dir/subdir/large.bin
   R dir/subdir/large.bin
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir2/
   .hglf/dir2/subdir/
   .hglf/dir2/subdir/large.bin
   .hglf/large
   dir2/
   dir2/subdir/
   dir2/subdir/large.bin
@@ -1216,17 +1216,17 @@ Start from scratch, and rename something
   $ hg revert --all
   forgetting .hglf/dir2/subdir/large.bin
   undeleting .hglf/dir/subdir/large.bin
   reverting subrepo no-largefiles
 
   $ hg status -C
   ? dir2/subdir/large.bin
 
-  $ $PYTHON $TESTDIR/list-tree.py .hglf dir* large*
+  $ "$PYTHON" $TESTDIR/list-tree.py .hglf dir* large*
   .hglf/
   .hglf/dir/
   .hglf/dir/subdir/
   .hglf/dir/subdir/large.bin
   .hglf/large
   dir/
   dir/subdir/
   dir/subdir/large.bin
--- a/tests/test-largefiles.t
+++ b/tests/test-largefiles.t
@@ -220,17 +220,17 @@ Test largefiles can be loaded in hgweb (
   > from mercurial.hgweb import hgweb
   > from mercurial.hgweb import wsgicgi
   > application = hgweb(b'.', b'test repo')
   > wsgicgi.launch(application)
   > EOF
   $ . "$TESTDIR/cgienv"
 
   $ SCRIPT_NAME='' \
-  > $PYTHON "$TESTTMP/hgweb.cgi" > /dev/null
+  > "$PYTHON" "$TESTTMP/hgweb.cgi" > /dev/null
 
 Test archiving the various revisions.  These hit corner cases known with
 archiving.
 
   $ hg archive -r 0 ../archive0
   $ hg archive -r 1 ../archive1
   $ hg archive -r 2 ../archive2
   $ hg archive -r 3 ../archive3
--- a/tests/test-lfs-largefiles.t
+++ b/tests/test-lfs-largefiles.t
@@ -196,17 +196,17 @@ standins.
 
 --------------------------------------------------------------------------------
 
 When both largefiles and lfs are configured to add by size, the tie goes to
 largefiles since it hooks cmdutil.add() and lfs hooks the filelog write in the
 commit.  By the time the commit occurs, the tracked file is smaller than the
 threshold (assuming it is > 41, so the standins don't become lfs objects).
 
-  $ $PYTHON -c 'import sys ; sys.stdout.write("y\n" * 1048576)' > large_by_size.bin
+  $ "$PYTHON" -c 'import sys ; sys.stdout.write("y\n" * 1048576)' > large_by_size.bin
   $ hg --config largefiles.minsize=1 ci -Am 'large by size'
   adding large_by_size.bin as a largefile
   $ hg manifest
   .hglf/large.bin
   .hglf/large_by_size.bin
   .hglf/lfs.bin
   lfs.txt
   normal.txt
--- a/tests/test-lfs-serve-access.t
+++ b/tests/test-lfs-serve-access.t
@@ -47,17 +47,17 @@ Downloads fail...
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   new changesets 525251863cad
   updating to branch default
   abort: LFS HTTP error: HTTP Error 400: no such method: .git (action=download)!
   [255]
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D525251863cad618e55d483555f3d00a2ca99597e x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 400 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
@@ -136,17 +136,17 @@ Blob URIs are correct when --prefix is u
   lfs: adding f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e to the usercache
   lfs: processed: f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
   lfs: downloaded 1 files (20 bytes)
    lfs.bin: remote created -> g
   getting lfs.bin
   lfs: found f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e in the local lfs store
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=capabilities HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST /subdir/mount/point/.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /subdir/mount/point/.hg/lfs/objects/f03217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e HTTP/1.1" 200 - (glob)
 
@@ -169,17 +169,17 @@ though the client doesn't send the blob.
       }
     ]
     "transfer": "basic"
   }
   $ find server2/.hg/store/lfs/objects | sort
   server2/.hg/store/lfs/objects
   server2/.hg/store/lfs/objects/f0
   server2/.hg/store/lfs/objects/f0/3217a32529a28a42d03b1244fe09b6e0f9fd06d7b966d4d50567be2abe6c0e
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
   $ cat $TESTTMP/errors.log
 
   $ cat >> $TESTTMP/lfsstoreerror.py <<EOF
   > import errno
   > from hgext.lfs import blobstore
   > 
   > _numverifies = 0
   > _readerr = True
@@ -281,17 +281,17 @@ Test an I/O error during the processing 
 
 Test a checksum failure during the processing of the GET request
 
   $ hg --config lfs.url=http://localhost:$HGPORT1/.git/info/lfs \
   >    -R client update -r tip
   abort: HTTP error: HTTP Error 422: corrupt blob (oid=276f73cfd75f9fb519810df5f5d96d6594ca2521abd86cbcd92122f7d51a1f3d, action=download)!
   [255]
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D392c05922088bacf8e68a6939b480017afbf245d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
@@ -433,17 +433,17 @@ the GET/PUT request.
         }
         "oid": "df14287d8d75f076a6459e7a3703ca583ca9fb3f4918caed10c77ac8622d49b3"
         "size": 13
       }
     ]
     "transfer": "basic"
   }
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 401 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=capabilities HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&bundlecaps=HG20%2Cbundle2%3DHG20%250Abookmarks%250Achangegroup%253D01%252C02%252C03%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps%250Arev-branch-cache%250Astream%253Dv2&cg=1&common=0000000000000000000000000000000000000000&heads=506bf3d83f78c54b89e81c6411adee19fdf02156+525251863cad618e55d483555f3d00a2ca99597e&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ partial-pull (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 401 - (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
--- a/tests/test-lfs-serve.t
+++ b/tests/test-lfs-serve.t
@@ -504,17 +504,17 @@ Only the files required by diff are pref
   diff -r 8374dc4052cb -r 9640b57e77b1 lfspair2.bin
   --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   +++ b/lfspair2.bin	Thu Jan 01 00:00:00 1970 +0000
   @@ -0,0 +1,1 @@
   +this is an lfs file too
 
 #endif
 
-  $ $PYTHON $TESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $TESTDIR/killdaemons.py $DAEMON_PIDS
 
 #if lfsremote-on
   $ cat $TESTTMP/errors.log | grep '^[A-Z]'
   Traceback (most recent call last):
   ValueError: no common changegroup version
   Traceback (most recent call last):
   ValueError: no common changegroup version
 #else
--- a/tests/test-lfs-test-server.t
+++ b/tests/test-lfs-test-server.t
@@ -31,17 +31,17 @@
   >     exe = os.path.join(path, 'lfs-test-server.exe')
   >     if os.path.exists(exe):
   >         with open('lfs-server.log', 'wb') as out:
   >             p = subprocess.Popen(exe, stdout=out, stderr=out)
   >             sys.stdout.write('%s\n' % p.pid)
   >             sys.exit(0)
   > sys.exit(1)
   > EOF
-  $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
+  $ "$PYTHON" $TESTTMP/spawn.py >> $DAEMON_PIDS
 #endif
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > lfs=
   > [lfs]
   > url=http://foo:bar@$LFS_HOST
   > track=all()
@@ -845,17 +845,17 @@ Check error message when object does not
   oid sha256:bdc26931acfb734b142a8d675f205becf27560dc461f501822de13274fe6fc8a
   size 6
   x-is-binary 0
   $ cd ..
   $ rm -rf `hg config lfs.usercache`
 
 (Restart the server in a different location so it no longer has the content)
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
 #if hg-server
   $ cat $TESTTMP/access.log $TESTTMP/errors.log
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "PUT /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 201 - (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "GET /.hg/lfs/objects/31cf46fbc4ecd458a0943c5b4881f1f5a6dd36c53d6167d5b69ac45149b38e5b HTTP/1.1" 200 - (glob)
   $LOCALIP - - [$LOGDATE$] "POST /.git/info/lfs/objects/batch HTTP/1.1" 200 - (glob)
@@ -883,17 +883,17 @@ Check error message when object does not
   $ mkdir $TESTTMP/lfs-server2
   $ cd $TESTTMP/lfs-server2
 #if no-windows git-server
   $ lfs-test-server &> lfs-server.log &
   $ echo $! >> $DAEMON_PIDS
 #endif
 
 #if windows git-server
-  $ $PYTHON $TESTTMP/spawn.py >> $DAEMON_PIDS
+  $ "$PYTHON" $TESTTMP/spawn.py >> $DAEMON_PIDS
 #endif
 
 #if hg-server
   $ hg init server2
   $ hg --config "lfs.usercache=$TESTTMP/servercache2" -R server2 serve -d \
   >    -p $HGPORT --pid-file=hg.pid -A $TESTTMP/access.log -E $TESTTMP/errors.log
   $ cat hg.pid >> $DAEMON_PIDS
 #endif
@@ -933,9 +933,9 @@ Check error message when object does not
         "size": 6
       }
     ]
     "transfer": "basic" (hg-server !)
   }
   abort: LFS server error for "a": The object does not exist!
   [255]
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
--- a/tests/test-lfs.t
+++ b/tests/test-lfs.t
@@ -481,17 +481,17 @@ enabled adds the lfs requirement
   $ hg init repo10
   $ cd repo10
   $ cat >> .hg/hgrc << EOF
   > [extensions]
   > lfs=
   > [lfs]
   > track=all()
   > EOF
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > def write(path, content):
   >     with open(path, 'wb') as f:
   >         f.write(content)
   > write('a', b'\0\0')
   > write('b', b'\1\n')
   > write('c', b'\1\n\0')
   > write('d', b'xx')
   > EOF
--- a/tests/test-logexchange.t
+++ b/tests/test-logexchange.t
@@ -1,14 +1,14 @@
 Testing the functionality to pull remotenames
 =============================================
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > [alias]
   > glog = log -G -T '{rev}:{node|short}  {desc}'
   > [extensions]
   > remotenames =
   > show =
   > EOF
 
 Making a server repo
--- a/tests/test-mactext.t
+++ b/tests/test-mactext.t
@@ -19,20 +19,20 @@
   [hooks]
   pretxncommit.cr = python:hgext.win32text.forbidcr
   pretxnchangegroup.cr = python:hgext.win32text.forbidcr
 
   $ echo hello > f
   $ hg add f
   $ hg ci -m 1
 
-  $ $PYTHON unix2mac.py f
+  $ "$PYTHON" unix2mac.py f
   $ hg ci -m 2
   attempt to commit or push text file(s) using CR line endings
   in dea860dc51ec: f
   transaction abort!
   rollback completed
   abort: pretxncommit.cr hook failed
   [255]
-  $ hg cat f | $PYTHON print.py
+  $ hg cat f | "$PYTHON" print.py
   hello<LF>
-  $ cat f | $PYTHON print.py
+  $ cat f | "$PYTHON" print.py
   hello<CR>
--- a/tests/test-merge-force.t
+++ b/tests/test-merge-force.t
@@ -5,36 +5,36 @@ file that was modified in the remote cha
 local changeset, and then modified in the working copy to match the
 remote content, then finally forgotten.
 
   $ hg init repo
   $ cd repo
 
 Create base changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 1
   $ hg addremove -q --similarity 0
   $ hg commit -qm 'base'
 
 Create remote changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 2
   $ hg addremove -q --similarity 0
   $ hg commit -qm 'remote'
 
 Create local changeset
 
   $ hg update -q 0
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 3
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 3
   $ hg addremove -q --similarity 0
   $ hg commit -qm 'local'
 
 Set up working directory
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*_*-untracked
   $ rm *_*_*_missing-*
 
   $ hg status -A
   M content1_content1_content1_content4-tracked
   M content1_content1_content3_content1-tracked
   M content1_content1_content3_content4-tracked
@@ -306,17 +306,17 @@ content1_content2_content2_content2-untr
 doesn't make sense since the file did not exist in the parent, but on the
 other hand, merged-in additions are reported as modifications, which is
 almost as strange.
 
 missing_missing_content3_missing-tracked becomes removed ('R'), even though
 the remote side did not touch the file
 
   $ checkstatus() {
-  >   for f in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 3`
+  >   for f in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 3`
   >   do
   >     echo
   >     hg status -A $f
   >     if test -f $f
   >     then
   >       cat $f
   >     else
   >       echo '<missing>'
@@ -687,17 +687,17 @@ the remote side did not touch the file
   content4
   
   R missing_missing_missing_missing-tracked
   <missing>
   
   missing_missing_missing_missing-untracked: * (glob)
   <missing>
 
-  $ for f in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 3`
+  $ for f in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 3`
   > do
   >   if test -f ${f}.orig
   >   then
   >     echo ${f}.orig:
   >     cat ${f}.orig
   >   fi
   > done
   content1_content2_content1_content4-tracked.orig:
@@ -829,17 +829,17 @@ Re-resolve and check status
   [1]
   $ checkstatus > $TESTTMP/status2 2>&1
   $ cmp $TESTTMP/status1 $TESTTMP/status2 || diff -U8 $TESTTMP/status1 $TESTTMP/status2
 
 Set up working directory again
 
   $ hg -q update --clean 2
   $ hg --config extensions.purge= purge
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 3 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 3 wc
   $ hg addremove -q --similarity 0
   $ hg forget *_*_*_*-untracked
   $ rm *_*_*_missing-*
 
 Merge with checkunknown = warn, see that behavior is the same as before
   $ hg merge -f --tool internal:merge3 'desc("remote")' --config merge.checkunknown=warn > $TESTTMP/merge-output-2 2>&1
   [1]
   $ cmp $TESTTMP/merge-output-1 $TESTTMP/merge-output-2 || diff -U8 $TESTTMP/merge-output-1 $TESTTMP/merge-output-2
--- a/tests/test-merge-tools.t
+++ b/tests/test-merge-tools.t
@@ -63,17 +63,17 @@ default is internal merge:
   $ beforemerge
   [merge-tools]
   # hg update -C 1
 
 hg merge -r 2
 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're
 running from a devel copy, not a temp installation
 
-  $ PATH="$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
+  $ PATH="$BINDIR:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
   merging f
   warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
   [1]
   $ aftermerge
   # cat f
   <<<<<<< working copy: ef83787e2614 - test: revision 1
@@ -112,31 +112,31 @@ simplest hgrc using false for merge:
   U f
 
 #if unix-permissions
 
 unexecutable file in $PATH shouldn't be found:
 
   $ echo "echo fail" > false
   $ hg up -qC 1
-  $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
+  $ PATH="`pwd`:$BINDIR:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
   merging f
   warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
   [1]
   $ rm false
 
 #endif
 
 executable directory in $PATH shouldn't be found:
 
   $ mkdir false
   $ hg up -qC 1
-  $ PATH="`pwd`:$BINDIR:/usr/sbin" $PYTHON "$BINDIR"/hg merge -r 2
+  $ PATH="`pwd`:$BINDIR:/usr/sbin" "$PYTHON" "$BINDIR"/hg merge -r 2
   merging f
   warning: conflicts while merging f! (edit, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
   [1]
   $ rmdir false
 
 true with higher .priority gets precedence:
--- a/tests/test-mq-eol.t
+++ b/tests/test-mq-eol.t
@@ -39,21 +39,21 @@ Test interactions between mq and patch.e
   $ hg init repo
   $ cd repo
   $ echo '\.diff' > .hgignore
   $ echo '\.rej' >> .hgignore
 
 
 Test different --eol values
 
-  $ $PYTHON -c 'open("a", "wb").write(b"a\nb\nc\nd\ne")'
+  $ "$PYTHON" -c 'open("a", "wb").write(b"a\nb\nc\nd\ne")'
   $ hg ci -Am adda
   adding .hgignore
   adding a
-  $ $PYTHON ../makepatch.py
+  $ "$PYTHON" ../makepatch.py
   $ hg qimport eol.diff
   adding eol.diff to series file
 
 should fail in strict mode
 
   $ hg qpush
   applying eol.diff
   patching file a
@@ -80,17 +80,17 @@ invalid eol
   patch queue now empty
 
 force LF
 
   $ hg --config patch.eol='CRLF' qpush
   applying eol.diff
   now at: eol.diff
   $ hg qrefresh
-  $ $PYTHON ../cateol.py .hg/patches/eol.diff
+  $ "$PYTHON" ../cateol.py .hg/patches/eol.diff
   # HG changeset patch<LF>
   # Parent  0d0bf99a8b7a3842c6f8ef09e34f69156c4bd9d0<LF>
   test message<LF>
   <LF>
   diff -r 0d0bf99a8b7a a<LF>
   --- a/a<LF>
   +++ b/a<LF>
   @@ -1,5 +1,5 @@<LF>
@@ -101,71 +101,71 @@ force LF
   -e<LF>
   \ No newline at end of file<LF>
   +a<CR><LF>
   +y<CR><LF>
   +c<CR><LF>
   +d<CR><LF>
   +z<LF>
   \ No newline at end of file<LF>
-  $ $PYTHON ../cateol.py a
+  $ "$PYTHON" ../cateol.py a
   a<CR><LF>
   y<CR><LF>
   c<CR><LF>
   d<CR><LF>
   z
   $ hg qpop
   popping eol.diff
   patch queue now empty
 
 push again forcing LF and compare revisions
 
   $ hg --config patch.eol='CRLF' qpush
   applying eol.diff
   now at: eol.diff
-  $ $PYTHON ../cateol.py a
+  $ "$PYTHON" ../cateol.py a
   a<CR><LF>
   y<CR><LF>
   c<CR><LF>
   d<CR><LF>
   z
   $ hg qpop
   popping eol.diff
   patch queue now empty
 
 push again without LF and compare revisions
 
   $ hg qpush
   applying eol.diff
   now at: eol.diff
-  $ $PYTHON ../cateol.py a
+  $ "$PYTHON" ../cateol.py a
   a<CR><LF>
   y<CR><LF>
   c<CR><LF>
   d<CR><LF>
   z
   $ hg qpop
   popping eol.diff
   patch queue now empty
   $ cd ..
 
 
 Test .rej file EOL are left unchanged
 
   $ hg init testeol
   $ cd testeol
-  $ $PYTHON -c "open('a', 'wb').write(b'1\r\n2\r\n3\r\n4')"
+  $ "$PYTHON" -c "open('a', 'wb').write(b'1\r\n2\r\n3\r\n4')"
   $ hg ci -Am adda
   adding a
-  $ $PYTHON -c "open('a', 'wb').write(b'1\r\n2\r\n33\r\n4')"
+  $ "$PYTHON" -c "open('a', 'wb').write(b'1\r\n2\r\n33\r\n4')"
   $ hg qnew patch1
   $ hg qpop
   popping patch1
   patch queue now empty
-  $ $PYTHON -c "open('a', 'wb').write(b'1\r\n22\r\n33\r\n4')"
+  $ "$PYTHON" -c "open('a', 'wb').write(b'1\r\n22\r\n33\r\n4')"
   $ hg ci -m changea
 
   $ hg --config 'patch.eol=LF' qpush
   applying patch1
   patching file a
   Hunk #1 FAILED at 0
   1 out of 1 hunks FAILED -- saving rejects to file a.rej
   patch failed, unable to continue (try -v)
--- a/tests/test-mq-missingfiles.t
+++ b/tests/test-mq-missingfiles.t
@@ -18,21 +18,21 @@ future qrefresh.
   > f.close()
   > EOF
 
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "mq=" >> $HGRCPATH
 
   $ hg init normal
   $ cd normal
-  $ $PYTHON ../writelines.py b 10 'a\n'
+  $ "$PYTHON" ../writelines.py b 10 'a\n'
   $ hg ci -Am addb
   adding b
   $ echo a > a
-  $ $PYTHON ../writelines.py b 2 'b\n' 10 'a\n' 2 'c\n'
+  $ "$PYTHON" ../writelines.py b 2 'b\n' 10 'a\n' 2 'c\n'
   $ echo c > c
   $ hg add a c
   $ hg qnew -f changeb
   $ hg qpop
   popping changeb
   patch queue now empty
   $ hg rm b
   $ hg ci -Am rmb
@@ -77,17 +77,17 @@ Display rejections:
 Test missing renamed file
 
   $ hg qpop
   popping changeb
   patch queue now empty
   $ hg up -qC 0
   $ echo a > a
   $ hg mv b bb
-  $ $PYTHON ../writelines.py bb 2 'b\n' 10 'a\n' 2 'c\n'
+  $ "$PYTHON" ../writelines.py bb 2 'b\n' 10 'a\n' 2 'c\n'
   $ echo c > c
   $ hg add a c
   $ hg qnew changebb
   $ hg qpop
   popping changebb
   patch queue now empty
   $ hg up -qC 1
   $ hg qpush
@@ -124,21 +124,21 @@ Test missing renamed file
   $ cd ..
 
 
   $ echo "[diff]" >> $HGRCPATH
   $ echo "git=1" >> $HGRCPATH
 
   $ hg init git
   $ cd git
-  $ $PYTHON ../writelines.py b 1 '\x00'
+  $ "$PYTHON" ../writelines.py b 1 '\x00'
   $ hg ci -Am addb
   adding b
   $ echo a > a
-  $ $PYTHON ../writelines.py b 1 '\x01' 1 '\x00'
+  $ "$PYTHON" ../writelines.py b 1 '\x01' 1 '\x00'
   $ echo c > c
   $ hg add a c
   $ hg qnew -f changeb
   $ hg qpop
   popping changeb
   patch queue now empty
   $ hg rm b
   $ hg ci -Am rmb
--- a/tests/test-mq-qimport.t
+++ b/tests/test-mq-qimport.t
@@ -144,20 +144,20 @@ qimport -f
   $ cat foo
   foo2
   $ hg qpop
   popping url.diff
   patch queue now empty
 
 build diff with CRLF
 
-  $ $PYTHON ../writelines.py b 5 'a\n' 5 'a\r\n'
+  $ "$PYTHON" ../writelines.py b 5 'a\n' 5 'a\r\n'
   $ hg ci -Am addb
   adding b
-  $ $PYTHON ../writelines.py b 2 'a\n' 10 'b\n' 2 'a\r\n'
+  $ "$PYTHON" ../writelines.py b 2 'a\n' 10 'b\n' 2 'a\r\n'
   $ hg diff > b.diff
   $ hg up -C
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
 qimport CRLF diff
 
   $ hg qimport b.diff
   adding b.diff to series file
--- a/tests/test-mq-qpush-fail.t
+++ b/tests/test-mq-qpush-fail.t
@@ -26,17 +26,17 @@ test qpush on empty series
   $ hg qnew --config 'mq.plain=true' -U bad-patch
   $ echo >> foo
   $ hg qrefresh
   $ hg qpop -a
   popping bad-patch
   popping patch2
   popping patch1
   patch queue now empty
-  $ $PYTHON -c 'import sys; getattr(sys.stdout, "buffer", sys.stdout).write(b"\xe9\n")' > message
+  $ "$PYTHON" -c 'import sys; getattr(sys.stdout, "buffer", sys.stdout).write(b"\xe9\n")' > message
   $ cat .hg/patches/bad-patch >> message
   $ mv message .hg/patches/bad-patch
   $ cat > $TESTTMP/wrapplayback.py <<EOF
   > import os
   > from mercurial import extensions, transaction
   > def wrapplayback(orig,
   >                  journal, report, opener, vfsmap, entries, backupentries,
   >                  unlink=True, checkambigfiles=None):
--- a/tests/test-mq-subrepo-svn.t
+++ b/tests/test-mq-subrepo-svn.t
@@ -19,19 +19,19 @@ fn to create new repository, and cd into
 
 
 handle svn subrepos safely
 
   $ svnadmin create svn-repo-2499
 
   $ SVNREPOPATH=`pwd`/svn-repo-2499/project
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
   $ mkdir -p svn-project-2499/trunk
   $ svn import -qm 'init project' svn-project-2499 "$SVNREPOURL"
 
 qnew on repo w/svn subrepo
   $ mkrepo repo-2499-svn-subrepo
   $ svn co "$SVNREPOURL"/trunk sub
--- a/tests/test-mq.t
+++ b/tests/test-mq.t
@@ -1123,19 +1123,19 @@ create a git patch
 
 create a git binary patch
 
   $ cat > writebin.py <<EOF
   > import sys
   > path = sys.argv[1]
   > open(path, 'wb').write(b'BIN\x00ARY')
   > EOF
-  $ $PYTHON writebin.py bucephalus
+  $ "$PYTHON" writebin.py bucephalus
 
-  $ $PYTHON "$TESTDIR/md5sum.py" bucephalus
+  $ "$PYTHON" "$TESTDIR/md5sum.py" bucephalus
   8ba2a2f3e77b55d03051ff9c24ad65e7  bucephalus
   $ hg add bucephalus
   $ hg qnew -f --git addbucephalus
   $ grep diff .hg/patches/addbucephalus
   diff --git a/bucephalus b/bucephalus
 
 
 check binary patches can be popped and pushed
@@ -1144,17 +1144,17 @@ check binary patches can be popped and p
   popping addbucephalus
   now at: addalexander
   $ test -f bucephalus && echo % bucephalus should not be there
   [1]
   $ hg qpush
   applying addbucephalus
   now at: addbucephalus
   $ test -f bucephalus
-  $ $PYTHON "$TESTDIR/md5sum.py" bucephalus
+  $ "$PYTHON" "$TESTDIR/md5sum.py" bucephalus
   8ba2a2f3e77b55d03051ff9c24ad65e7  bucephalus
 
 
 
 strip again
 
   $ cd ..
   $ hg init strip
@@ -1570,17 +1570,17 @@ Test that secret mq patch does not break
   > HGWEB
   $ . "$TESTDIR/cgienv"
 #if msys
   $ PATH_INFO=//tags; export PATH_INFO
 #else
   $ PATH_INFO=/tags; export PATH_INFO
 #endif
   $ QUERY_STRING='style=raw'
-  $ $PYTHON hgweb.cgi | grep '^tip'
+  $ "$PYTHON" hgweb.cgi | grep '^tip'
   tip	[0-9a-f]{40} (re)
 
   $ cd ..
 
 Test interaction with revset (issue4426)
 
   $ hg init issue4426
   $ cd issue4426
--- a/tests/test-narrow-clone-non-narrow-server.t
+++ b/tests/test-narrow-clone-non-narrow-server.t
@@ -26,17 +26,17 @@ Verify that narrow is advertised in the 
   >     import urllib.parse as up
   >     unquote = up.unquote_plus
   > else:
   >     import urllib
   >     unquote = urllib.unquote_plus
   > print(unquote(list(sys.stdin)[1]))
   > EOF
   $ echo hello | hg -R . serve --stdio | \
-  >   $PYTHON unquote.py | grep narrow
+  >   "$PYTHON" unquote.py | grep narrow
   narrow=v0
   rev-branch-cache changegroupsubset exp-narrow-1 getbundle known lookup protocaps pushkey streamreqs=generaldelta,revlogv1 unbundle=HG10GZ,HG10BZ,HG10UN unbundlehash
 
   $ cd ..
 
   $ hg clone --narrow --include f1 http://localhost:$HGPORT1/ narrowclone
   requesting all changes
   abort: server doesn't support narrow clones
--- a/tests/test-newcgi.t
+++ b/tests/test-newcgi.t
@@ -47,20 +47,20 @@ before d74fc8dec2b4 still work.
   >     return hgwebdir("hgweb.config")
   > 
   > wsgicgi.launch(wsgiapplication(make_web_app))
   > HGWEBDIR
 
   $ chmod 755 hgwebdir.cgi
 
   $ . "$TESTDIR/cgienv"
-  $ $PYTHON hgweb.cgi > page1
-  $ $PYTHON hgwebdir.cgi > page2
+  $ "$PYTHON" hgweb.cgi > page1
+  $ "$PYTHON" hgwebdir.cgi > page2
 
   $ PATH_INFO="/test/"
   $ PATH_TRANSLATED="/var/something/test.cgi"
   $ REQUEST_URI="/test/test/"
   $ SCRIPT_URI="http://hg.omnifarious.org/test/test/"
   $ SCRIPT_URL="/test/test/"
-  $ $PYTHON hgwebdir.cgi > page3
+  $ "$PYTHON" hgwebdir.cgi > page3
 
   $ grep -i error page1 page2 page3
   [1]
--- a/tests/test-newercgi.t
+++ b/tests/test-newercgi.t
@@ -41,20 +41,20 @@ This is a rudimentary test of the CGI fi
   > 
   > application = hgwebdir("hgweb.config")
   > wsgicgi.launch(application)
   > HGWEBDIR
 
   $ chmod 755 hgwebdir.cgi
 
   $ . "$TESTDIR/cgienv"
-  $ $PYTHON hgweb.cgi > page1
-  $ $PYTHON hgwebdir.cgi > page2
+  $ "$PYTHON" hgweb.cgi > page1
+  $ "$PYTHON" hgwebdir.cgi > page2
 
   $ PATH_INFO="/test/"
   $ PATH_TRANSLATED="/var/something/test.cgi"
   $ REQUEST_URI="/test/test/"
   $ SCRIPT_URI="http://hg.omnifarious.org/test/test/"
   $ SCRIPT_URL="/test/test/"
-  $ $PYTHON hgwebdir.cgi > page3
+  $ "$PYTHON" hgwebdir.cgi > page3
 
   $ grep -i error page1 page2 page3
   [1]
--- a/tests/test-notify-changegroup.t
+++ b/tests/test-notify-changegroup.t
@@ -34,17 +34,17 @@ commit
 
 commit
 
   $ hg --traceback --cwd b commit -Amb
 
 push
 
   $ hg --traceback --cwd b push ../a 2>&1 |
-  >     $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
+  >     "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
   pushing to ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
@@ -88,17 +88,17 @@ unbundle with unrelated source
   new changesets cb9a9f314b8b:ba677d0156c1 (2 drafts)
   (run 'hg update' to get a working copy)
   $ hg --cwd a rollback
   repository tip rolled back to revision -1 (undo unbundle)
 
 unbundle with correct source
 
   $ hg --config notify.sources=unbundle --cwd a unbundle ../test.hg 2>&1 |
-  >     $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
+  >     "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
   adding changesets
   adding manifests
   adding file changes
   added 2 changesets with 2 changes to 1 files
   new changesets cb9a9f314b8b:ba677d0156c1 (2 drafts)
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
@@ -164,17 +164,17 @@ merge as a different user
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
   $ hg --traceback --cwd b commit -Am "merged"
 
 push
 
   $ hg --traceback --cwd b --config notify.fromauthor=True push ../a 2>&1 |
-  >     $PYTHON -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
+  >     "$PYTHON" -c 'from __future__ import print_function ; import sys,re; print(re.sub("\n\t", " ", sys.stdin.read()), end="")'
   pushing to ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 4 changesets with 4 changes to 1 files
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
--- a/tests/test-notify.t
+++ b/tests/test-notify.t
@@ -185,17 +185,17 @@ on Mac OS X 10.5 the tmp path is very lo
   > [notify]
   > maxsubject = 200
   > EOF
 
 the python call below wraps continuation lines, which appear on Mac OS X 10.5 because
 of the very long subject line
 pull (minimal config)
 
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
   new changesets 00a13f371396
   MIME-Version: 1.0
@@ -244,17 +244,17 @@ fail for config file is missing
   $ hg --cwd b pull ../a 2>&1 | grep 'error.*\.notify\.conf' > /dev/null && echo pull failed
   pull failed
   $ touch ".notify.conf"
 
 pull
 
   $ hg --cwd b rollback
   repository tip rolled back to revision 0 (undo pull)
-  $ hg --traceback --cwd b pull ../a  | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a  | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
   new changesets 00a13f371396
   MIME-Version: 1.0
@@ -292,17 +292,17 @@ pull
   > sources = pull
   > diffstat = True
   > EOF
 
 pull
 
   $ hg --cwd b rollback
   repository tip rolled back to revision 0 (undo pull)
-  $ hg --traceback --config notify.maxdiffstat=1 --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --config notify.maxdiffstat=1 --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 2 changes to 2 files
   new changesets 00a13f371396
   MIME-Version: 1.0
@@ -343,17 +343,17 @@ test merge
   $ echo a >> a
   $ hg ci -Am adda2 -d '2 0'
   created new head
   $ hg merge
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg ci -m merge -d '3 0'
   $ cd ..
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 2 changesets with 0 changes to 0 files
   new changesets 3332653e1f3c:fccf66cd0c35
   MIME-Version: 1.0
@@ -407,19 +407,19 @@ test merge
 non-ascii content and truncation of multi-byte subject
 
   $ cat <<EOF >> $HGRCPATH
   > [notify]
   > maxsubject = 4
   > EOF
   $ echo a >> a/a
   $ hg --cwd a --encoding utf-8 commit -A -d '0 0' \
-  >   -m `$PYTHON -c 'print "\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4"'`
+  >   -m `"$PYTHON" -c 'print "\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4"'`
   $ hg --traceback --cwd b --encoding utf-8 pull ../a | \
-  >   $PYTHON $TESTTMP/filter.py
+  >   "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   new changesets 0f25f9c22b4c
   MIME-Version: 1.0
@@ -450,29 +450,29 @@ non-ascii content and truncation of mult
 long lines
 
   $ cat <<EOF >> $HGRCPATH
   > [notify]
   > maxsubject = 67
   > test = False
   > mbox = mbox
   > EOF
-  $ $PYTHON -c 'open("a/a", "ab").write("no" * 500 + "\xd1\x84" + "\n")'
+  $ "$PYTHON" -c 'open("a/a", "ab").write("no" * 500 + "\xd1\x84" + "\n")'
   $ hg --cwd a commit -A -m "long line"
   $ hg --traceback --cwd b pull ../a
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   new changesets a846b5f6ebb7
   notify: sending 2 subscribers 1 changes
   (run 'hg update' to get a working copy)
-  $ $PYTHON $TESTTMP/filter.py < b/mbox
+  $ "$PYTHON" $TESTTMP/filter.py < b/mbox
   From test@test.com ... ... .. ..:..:.. .... (re)
   MIME-Version: 1.0
   Content-Type: text/plain; charset="*" (glob)
   Content-Transfer-Encoding: quoted-printable
   X-Test: foo
   Date: * (glob)
   Subject: long line
   From: test@test.com
@@ -522,17 +522,17 @@ long lines
   > */a#branch(test) = will_no_be_send@example.com
   > */b#branch(test) = notify@example.com
   > EOF
   $ hg --cwd a branch test
   marked working directory as branch test
   (branches are permanent and global, did you want a bookmark?)
   $ echo a >> a/a
   $ hg --cwd a ci -m test -d '1 0'
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
   new changesets f7e5aaed4080
   MIME-Version: 1.0
@@ -552,17 +552,17 @@ long lines
 
 revset selection: don't send to address that waits for mails
 from different branch
 
   $ hg --cwd a update default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo a >> a/a
   $ hg --cwd a ci -m test -d '1 0'
-  $ hg --traceback --cwd b pull ../a | $PYTHON $TESTTMP/filter.py
+  $ hg --traceback --cwd b pull ../a | "$PYTHON" $TESTTMP/filter.py
   pulling from ../a
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 0 changes to 0 files (+1 heads)
   new changesets 645eb6690ecf
   MIME-Version: 1.0
@@ -581,17 +581,17 @@ from different branch
   (run 'hg heads' to see heads)
 
 default template:
 
   $ grep -v '^template =' $HGRCPATH > "$HGRCPATH.new"
   $ mv "$HGRCPATH.new" $HGRCPATH
   $ echo a >> a/a
   $ hg --cwd a commit -m 'default template'
-  $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py
+  $ hg --cwd b pull ../a -q | "$PYTHON" $TESTTMP/filter.py
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
   Date: * (glob)
   Subject: changeset in b: default template
   From: test@test.com
   X-Hg-Notification: changeset 5cd4346eed47
   Message-Id: <hg.5cd4346eed47.*.*@*> (glob)
@@ -610,17 +610,17 @@ with style:
   >              changeset {node|short}"
   > EOF
   $ cat <<EOF >> $HGRCPATH
   > [notify]
   > style = $TESTTMP/notifystyle.map
   > EOF
   $ echo a >> a/a
   $ hg --cwd a commit -m 'with style'
-  $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py
+  $ hg --cwd b pull ../a -q | "$PYTHON" $TESTTMP/filter.py
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
   Date: * (glob)
   Subject: with style
   From: test@test.com
   X-Hg-Notification: changeset ec8d9d852f56
   Message-Id: <hg.ec8d9d852f56.*.*@*> (glob)
@@ -633,17 +633,17 @@ with template (overrides style):
   $ cat <<EOF >> $HGRCPATH
   > template = Subject: {node|short}: {desc|firstline|strip}
   >            From: {author}
   >            {""}
   >            {desc}
   > EOF
   $ echo a >> a/a
   $ hg --cwd a commit -m 'with template'
-  $ hg --cwd b pull ../a -q | $PYTHON $TESTTMP/filter.py
+  $ hg --cwd b pull ../a -q | "$PYTHON" $TESTTMP/filter.py
   MIME-Version: 1.0
   Content-Type: text/plain; charset="us-ascii"
   Content-Transfer-Encoding: 7bit
   Date: * (glob)
   Subject: 14721b538ae3: with template
   From: test@test.com
   X-Hg-Notification: changeset 14721b538ae3
   Message-Id: <hg.14721b538ae3.*.*@*> (glob)
--- a/tests/test-obsmarker-template.t
+++ b/tests/test-obsmarker-template.t
@@ -2586,17 +2586,17 @@ Test metadata encoding (issue5754)
 ==================================
 
   $ hg init $TESTTMP/metadata-encoding
   $ cd $TESTTMP/metadata-encoding
   $ cat <<'EOF' >> .hg/hgrc
   > [extensions]
   > amend =
   > EOF
-  $ $PYTHON <<'EOF'
+  $ "$PYTHON" <<'EOF'
   > with open('test1', 'wb') as f:
   >    f.write(b't\xe8st1') and None
   > with open('test2', 'wb') as f:
   >    f.write(b't\xe8st2') and None
   > EOF
   $ mkcommit ROOT
   $ ( HGENCODING=latin-1 HGUSER="`cat test1`" mkcommit A0 )
   $ echo 42 >> A0
--- a/tests/test-oldcgi.t
+++ b/tests/test-oldcgi.t
@@ -1,15 +1,15 @@
 #require no-msys # MSYS will translate web paths as if they were file paths
 
 This tests if CGI files from before d0db3462d568 still work.
 
   $ hg init test
   $ cat >hgweb.cgi <<HGWEB
-  > #!$PYTHON
+  > #!"$PYTHON"
   > #
   > # An example CGI script to use hgweb, edit as necessary
   > 
   > import cgitb, os, sys
   > cgitb.enable()
   > 
   > # sys.path.insert(0, "/path/to/python/lib") # if not a system-wide install
   > from mercurial import hgweb
@@ -21,17 +21,17 @@ This tests if CGI files from before d0db
   $ chmod 755 hgweb.cgi
 
   $ cat >hgweb.config <<HGWEBDIRCONF
   > [paths]
   > test = test
   > HGWEBDIRCONF
 
   $ cat >hgwebdir.cgi <<HGWEBDIR
-  > #!$PYTHON
+  > #!"$PYTHON"
   > #
   > # An example CGI script to export multiple hgweb repos, edit as necessary
   > 
   > import cgitb, sys
   > cgitb.enable()
   > 
   > # sys.path.insert(0, "/path/to/python/lib") # if not a system-wide install
   > from mercurial import hgweb
@@ -57,20 +57,20 @@ This tests if CGI files from before d0db
   > 
   > h = hgweb.hgwebdir("hgweb.config")
   > h.run()
   > HGWEBDIR
 
   $ chmod 755 hgwebdir.cgi
 
   $ . "$TESTDIR/cgienv"
-  $ $PYTHON hgweb.cgi > page1
-  $ $PYTHON hgwebdir.cgi > page2
+  $ "$PYTHON" hgweb.cgi > page1
+  $ "$PYTHON" hgwebdir.cgi > page2
 
   $ PATH_INFO="/test/"
   $ PATH_TRANSLATED="/var/something/test.cgi"
   $ REQUEST_URI="/test/test/"
   $ SCRIPT_URI="http://hg.omnifarious.org/test/test/"
   $ SCRIPT_URL="/test/test/"
-  $ $PYTHON hgwebdir.cgi > page3
+  $ "$PYTHON" hgwebdir.cgi > page3
 
   $ grep -i error page1 page2 page3
   [1]
--- a/tests/test-pager-legacy.t
+++ b/tests/test-pager-legacy.t
@@ -9,25 +9,25 @@ pager and tell it to use our fake pager 
 pager was running.
   $ cat >> $HGRCPATH <<EOF
   > [ui]
   > formatted = yes
   > color = no
   > [extensions]
   > pager=
   > [pager]
-  > pager = $PYTHON $TESTTMP/fakepager.py
+  > pager = "$PYTHON" $TESTTMP/fakepager.py
   > EOF
 
   $ hg init repo
   $ cd repo
   $ echo a >> a
   $ hg add a
   $ hg ci -m 'add a'
-  $ for x in `$PYTHON $TESTDIR/seq.py 1 10`; do
+  $ for x in `"$PYTHON" $TESTDIR/seq.py 1 10`; do
   >   echo a $x >> a
   >   hg ci -m "modify a $x"
   > done
 
 By default diff and log are paged, but summary is not:
 
   $ hg diff -c 2 --pager=yes
   paged! 'diff -r f4be7687d414 -r bce265549556 a\n'
--- a/tests/test-pager.t
+++ b/tests/test-pager.t
@@ -11,25 +11,25 @@
 Enable ui.formatted because pager won't fire without it, and set up
 pager and tell it to use our fake pager that lets us see when the
 pager was running.
   $ cat >> $HGRCPATH <<EOF
   > [ui]
   > formatted = yes
   > color = no
   > [pager]
-  > pager = $PYTHON $TESTTMP/fakepager.py
+  > pager = "$PYTHON" $TESTTMP/fakepager.py
   > EOF
 
   $ hg init repo
   $ cd repo
   $ echo a >> a
   $ hg add a
   $ hg ci -m 'add a'
-  $ for x in `$PYTHON $TESTDIR/seq.py 1 10`; do
+  $ for x in `"$PYTHON" $TESTDIR/seq.py 1 10`; do
   >   echo a $x >> a
   >   hg ci -m "modify a $x"
   > done
 
 By default diff and log are paged, but id is not:
 
   $ hg diff -c 2 --pager=yes
   paged! 'diff -r f4be7687d414 -r bce265549556 a\n'
@@ -399,17 +399,17 @@ Environment variables like LESS and LV a
   > EOF
 
   $ cat >> $HGRCPATH <<EOF
   > [alias]
   > noop = log -r 0 -T ''
   > [ui]
   > formatted=1
   > [pager]
-  > pager = $PYTHON $TESTTMP/printlesslv.py
+  > pager = "$PYTHON" $TESTTMP/printlesslv.py
   > EOF
   $ unset LESS
   $ unset LV
   $ hg noop --pager=on
   LESS=FRX
   LV=-c
   $ LESS=EFGH hg noop --pager=on
   LESS=EFGH
--- a/tests/test-parseindex.t
+++ b/tests/test-parseindex.t
@@ -56,30 +56,30 @@ We approximate that by reducing the read
   >         return singlebyteread(f)
   >     return wrapper
   > 
   > cl = changelog.changelog(opener('.hg/store'))
   > print(len(cl), 'revisions:')
   > for r in cl:
   >     print(short(cl.node(r)))
   > EOF
-  $ $PYTHON test.py
+  $ "$PYTHON" test.py
   2 revisions:
   7c31755bf9b5
   26333235a41c
 
   $ cd ..
 
 #if no-pure
 
 Test SEGV caused by bad revision passed to reachableroots() (issue4775):
 
   $ cd a
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > from __future__ import print_function
   > from mercurial import changelog, vfs
   > cl = changelog.changelog(vfs.vfs('.hg/store'))
   > print('good heads:')
   > for head in [0, len(cl) - 1, -1]:
   >     print('%s: %r' % (head, cl.reachableroots(0, [head], [0])))
   > print('bad heads:')
   > for head in [len(cl), 10000, -2, -10000, None]:
@@ -132,17 +132,17 @@ Test corrupted p1/p2 fields that could c
 
   $ mkdir invalidparent
   $ cd invalidparent
 
   $ hg clone --pull -q --config phases.publish=False ../a limit
   $ hg clone --pull -q --config phases.publish=False ../a segv
   $ rm -R limit/.hg/cache segv/.hg/cache
 
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > data = open("limit/.hg/store/00changelog.i", "rb").read()
   > for n, p in [(b'limit', b'\0\0\0\x02'), (b'segv', b'\0\x01\0\0')]:
   >     # corrupt p1 at rev0 and p2 at rev1
   >     d = data[:24] + p + data[28:127 + 28] + p + data[127 + 32:]
   >     open(n + b"/.hg/store/00changelog.i", "wb").write(d)
   > EOF
 
   $ hg -R limit debugrevlogindex -f1 -c
@@ -183,23 +183,23 @@ Test corrupted p1/p2 fields that could c
   >     print(l + ':', end=' ')
   >     try:
   >         f()
   >         print('uncaught buffer overflow?')
   >     except ValueError as inst:
   >         print(inst)
   > EOF
 
-  $ $PYTHON test.py limit/.hg/store
+  $ "$PYTHON" test.py limit/.hg/store
   reachableroots: parent out of range
   compute_phases_map_sets: parent out of range
   index_headrevs: parent out of range
   find_gca_candidates: parent out of range
   find_deepest: parent out of range
-  $ $PYTHON test.py segv/.hg/store
+  $ "$PYTHON" test.py segv/.hg/store
   reachableroots: parent out of range
   compute_phases_map_sets: parent out of range
   index_headrevs: parent out of range
   find_gca_candidates: parent out of range
   find_deepest: parent out of range
 
   $ cd ..
 
--- a/tests/test-patch-offset.t
+++ b/tests/test-patch-offset.t
@@ -18,17 +18,17 @@ prepare repo
   $ hg init a
   $ cd a
 
 These initial lines of Xs were not in the original file used to generate
 the patch.  So all the patch hunks need to be applied to a constant offset
 within this file.  If the offset isn't tracked then the hunks can be
 applied to the wrong lines of this file.
 
-  $ $PYTHON ../writepatterns.py a 34X 10A 1B 10A 1C 10A 1B 10A 1D 10A 1B 10A 1E 10A 1B 10A
+  $ "$PYTHON" ../writepatterns.py a 34X 10A 1B 10A 1C 10A 1B 10A 1D 10A 1B 10A 1E 10A 1B 10A
   $ hg commit -Am adda
   adding a
 
 This is a cleaner patch generated via diff
 In this case it reproduces the problem when
 the output of hg export does not
 import patch
 
@@ -71,12 +71,12 @@ import patch
   committing files:
   a
   committing manifest
   committing changelog
   created 189885cecb41
 
 compare imported changes against reference file
 
-  $ $PYTHON ../writepatterns.py aref 34X 10A 1B 1a 9A 1C 10A 1B 10A 1D 10A 1B 1a 9A 1E 10A 1B 1a 9A
+  $ "$PYTHON" ../writepatterns.py aref 34X 10A 1B 1a 9A 1C 10A 1B 10A 1D 10A 1B 1a 9A 1E 10A 1B 1a 9A
   $ diff aref a
 
   $ cd ..
--- a/tests/test-patch.t
+++ b/tests/test-patch.t
@@ -2,17 +2,17 @@
   > from __future__ import absolute_import, print_function
   > import sys
   > print('Using custom patch')
   > if '--binary' in sys.argv:
   >     print('--binary found !')
   > EOF
 
   $ echo "[ui]" >> $HGRCPATH
-  $ echo "patch=$PYTHON ../patchtool.py" >> $HGRCPATH
+  $ echo "patch=\"$PYTHON\" ../patchtool.py" >> $HGRCPATH
 
   $ hg init a
   $ cd a
   $ echo a > a
   $ hg commit -Ama -d '1 0'
   adding a
   $ echo b >> a
   $ hg commit -Amb -d '2 0'
--- a/tests/test-patchbomb-tls.t
+++ b/tests/test-patchbomb-tls.t
@@ -1,16 +1,16 @@
 #require serve ssl
 
 Set up SMTP server:
 
   $ CERTSDIR="$TESTDIR/sslcerts"
   $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
 
-  $ $PYTHON "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \
+  $ "$PYTHON" "$TESTDIR/dummysmtpd.py" -p $HGPORT --pid-file a.pid -d \
   > --tls smtps --certificate `pwd`/server.pem
   listening at localhost:$HGPORT (?)
   $ cat a.pid >> $DAEMON_PIDS
 
 Set up repository:
 
   $ hg init t
   $ cd t
--- a/tests/test-patchbomb.t
+++ b/tests/test-patchbomb.t
@@ -437,17 +437,17 @@ with a specific bundle type
   wKYXKqUJwqnG5sYWSWmmJsaWlqYWaRaWJpaWiWamZpYWRgZGxolJiabmSQbmZqlcQMV6QGwCxGzG
   CgZcySARUyA2A2LGZKiZ3Y+Lu786z4z4MWXmsrAZCsqrl1az5y21PMcjpbThzWeXGT+/nutbmvvz
   zXYS3BoGxdrJDIYmlimJJiZpRokmqYYmaSYWFknmSSkmhqbmliamiZYWxuYmBhbJBgZcUBNZQe5K
   Epm7xF/LT+RLx/a9juFTomaYO/Rgsx4rwBN+IMCUDLOKAQBrsmti
    (?)
   --===============*==-- (glob)
 
 utf-8 patch:
-  $ $PYTHON -c 'fp = open("utf", "wb"); fp.write(b"h\xC3\xB6mma!\n"); fp.close();'
+  $ "$PYTHON" -c 'fp = open("utf", "wb"); fp.write(b"h\xC3\xB6mma!\n"); fp.close();'
   $ hg commit -A -d '4 0' -m 'utf-8 content'
   adding description
   adding utf
 
 no mime encoding for email --test:
   $ hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -n
   this patch series consists of 1 patches.
   
@@ -553,17 +553,17 @@ mime encoded mbox (base64):
   --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   +++ b/utf	Thu Jan 01 00:00:04 1970 +0000
   @@ -0,0 +1,1 @@
   +h\xc3\xb6mma! (esc)
   
   $ rm mbox
 
 mime encoded mbox (quoted-printable):
-  $ $PYTHON -c 'fp = open("long", "wb"); fp.write(b"%s\nfoo\n\nbar\n" % (b"x" * 1024)); fp.close();'
+  $ "$PYTHON" -c 'fp = open("long", "wb"); fp.write(b"%s\nfoo\n\nbar\n" % (b"x" * 1024)); fp.close();'
   $ hg commit -A -d '4 0' -m 'long line'
   adding long
 
 no mime encoding for email --test:
   $ hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -n
   this patch series consists of 1 patches.
   
   
@@ -667,17 +667,17 @@ mime encoded mbox (quoted-printable):
   +
   +bar
   
   
 
   $ rm mbox
 
 iso-8859-1 patch:
-  $ $PYTHON -c 'fp = open("isolatin", "wb"); fp.write(b"h\xF6mma!\n"); fp.close();'
+  $ "$PYTHON" -c 'fp = open("isolatin", "wb"); fp.write(b"h\xF6mma!\n"); fp.close();'
   $ hg commit -A -d '5 0' -m 'isolatin 8-bit encoding'
   adding isolatin
 
 iso-8859-1 mbox:
   $ hg email --date '1970-1-1 0:5' -f quux -t foo -c bar -r tip -m mbox
   this patch series consists of 1 patches.
   
   
--- a/tests/test-profile.t
+++ b/tests/test-profile.t
@@ -100,17 +100,17 @@ Various statprof formatters work
   $ cat ../out | statprofran
 
   $ hg --profile --config profiling.statformat=json sleep 2>../out
   $ cat ../out
   \[\[-?\d+.* (re)
 
 statprof can be used as a standalone module
 
-  $ $PYTHON -m mercurial.statprof hotpath
+  $ "$PYTHON" -m mercurial.statprof hotpath
   must specify --file to load
   [1]
 
   $ cd ..
 
 #if no-chg
 profiler extension could be loaded before other extensions
 
--- a/tests/test-pull.t
+++ b/tests/test-pull.t
@@ -104,22 +104,22 @@ MSYS changes 'file:' into 'file;'
 
 #if no-msys
   $ hg pull -q file:../test  # no-msys
 #endif
 
 It's tricky to make file:// URLs working on every platform with
 regular shell commands.
 
-  $ URL=`$PYTHON -c "from __future__ import print_function; import os; print('file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
+  $ URL=`"$PYTHON" -c "from __future__ import print_function; import os; print('file://foobar' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
   $ hg pull -q "$URL"
   abort: file:// URLs can only refer to localhost
   [255]
 
-  $ URL=`$PYTHON -c "from __future__ import print_function; import os; print('file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
+  $ URL=`"$PYTHON" -c "from __future__ import print_function; import os; print('file://localhost' + ('/' + os.getcwd().replace(os.sep, '/')).replace('//', '/') + '/../test')"`
   $ hg pull -q "$URL"
 
 SEC: check for unsafe ssh url
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
   > ssh = sh -c "read l; read l; read l"
   > EOF
--- a/tests/test-purge.t
+++ b/tests/test-purge.t
@@ -44,17 +44,17 @@ delete an untracked directory
   $ ls
   directory
   r1
 
 delete an untracked file
 
   $ touch untracked_file
   $ touch untracked_file_readonly
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > import os, stat
   > f= 'untracked_file_readonly'
   > os.chmod(f, stat.S_IMODE(os.stat(f).st_mode) & ~stat.S_IWRITE)
   > EOF
   $ hg purge -p
   untracked_file
   untracked_file_readonly
   $ hg purge -v
--- a/tests/test-push-cgi.t
+++ b/tests/test-push-cgi.t
@@ -33,59 +33,59 @@ test preparation
   $ CONTENT_TYPE="application/octet-stream"; export CONTENT_TYPE
   $ hg bundle --type v1 --all bundle.hg
   1 changesets found
   $ CONTENT_LENGTH=279; export CONTENT_LENGTH;
 
 expect failure because heads doesn't match (formerly known as 'unsynced changes')
 
   $ QUERY_STRING="cmd=unbundle&heads=0000000000000000000000000000000000000000"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page1 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page1 2>&1
   $ cat page1
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 64\r (esc)
   \r (esc)
   0
   repository changed while preparing changes - please try again
 
 successful force push
 
   $ QUERY_STRING="cmd=unbundle&heads=666f726365"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page2 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page2 2>&1
   $ cat page2
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 102\r (esc)
   \r (esc)
   1
   adding changesets
   adding manifests
   adding file changes
   added 0 changesets with 0 changes to 1 files
 
 successful push, list of heads
 
   $ QUERY_STRING="cmd=unbundle&heads=f7b1eb17ad24730a1651fccd46c43826d1bbc2ac"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page3 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page3 2>&1
   $ cat page3
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 102\r (esc)
   \r (esc)
   1
   adding changesets
   adding manifests
   adding file changes
   added 0 changesets with 0 changes to 1 files
 
 successful push, SHA1 hash of heads (unbundlehash capability)
 
   $ QUERY_STRING="cmd=unbundle&heads=686173686564 5a785a5f9e0d433b88ed862b206b011b0c3a9d13"; export QUERY_STRING
-  $ $PYTHON hgweb.cgi <bundle.hg >page4 2>&1
+  $ "$PYTHON" hgweb.cgi <bundle.hg >page4 2>&1
   $ cat page4
   Status: 200 Script output follows\r (esc)
   Content-Type: application/mercurial-0.1\r (esc)
   Content-Length: 102\r (esc)
   \r (esc)
   1
   adding changesets
   adding manifests
--- a/tests/test-push-race.t
+++ b/tests/test-push-race.t
@@ -97,17 +97,17 @@ A set of extension and shell functions e
   >              break
   >         fi;
   >     done
   >     [ ! -f $1 ] || echo "delay file still exist: $1"
   > }
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > # simplify output
   > logtemplate = {node|short} {desc} ({branch})
   > [phases]
   > publish = no
   > [experimental]
   > evolution=true
   > [alias]
   > graph = log -G --rev 'sort(all(), "topo")'
--- a/tests/test-push-warn.t
+++ b/tests/test-push-warn.t
@@ -414,17 +414,17 @@ multiple new heads but also doesn't repo
   created new head
   $ hg -R i up 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ echo c > i/c
   $ hg -R i ci -Am c
   adding c
   created new head
 
-  $ for i in `$PYTHON $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
 
   $ hg -R i push h
   pushing to h
   searching for changes
   remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
   abort: push creates new remote head 97bd0c84d346!
   (pull and merge or see 'hg help push' for details about pushing new heads)
   [255]
--- a/tests/test-rebase-base-flag.t
+++ b/tests/test-rebase-base-flag.t
@@ -9,17 +9,17 @@ flag should probably live in somewhere e
   > [phases]
   > publish=False
   > 
   > [alias]
   > tglog = log -G --template "{rev}: {node|short} {desc}"
   > EOF
 
   $ rebasewithdag() {
-  >   N=`$PYTHON -c "print($N+1)"`
+  >   N=`"$PYTHON" -c "print($N+1)"`
   >   hg init repo$N && cd repo$N
   >   hg debugdrawdag
   >   hg rebase "$@" > _rebasetmp
   >   r=$?
   >   grep -v 'saved backup bundle' _rebasetmp
   >   [ $r -eq 0 ] && hg tglog
   >   cd ..
   >   return $r
--- a/tests/test-rebase-dest.t
+++ b/tests/test-rebase-dest.t
@@ -114,17 +114,17 @@ Setup rebase with multiple destinations
   > tglog = log -G --template "{rev}: {node|short} {desc} {instabilities}" -r 'sort(all(), topo)'
   > [extensions]
   > maprevset=$TESTTMP/maprevset.py
   > [experimental]
   > evolution=true
   > EOF
 
   $ rebasewithdag() {
-  >   N=`$PYTHON -c "print($N+1)"`
+  >   N=`"$PYTHON" -c "print($N+1)"`
   >   hg init repo$N && cd repo$N
   >   hg debugdrawdag
   >   hg rebase "$@" > _rebasetmp
   >   r=$?
   >   grep -v 'saved backup bundle' _rebasetmp
   >   [ $r -eq 0 ] && rm -f .hg/localtags && hg tglog
   >   cd ..
   >   return $r
--- a/tests/test-rebase-partial.t
+++ b/tests/test-rebase-partial.t
@@ -10,17 +10,17 @@ destination (issue5422)
   > evolution.createmarkers=True
   > evolution.allowunstable=True
   > 
   > [alias]
   > tglog = log -G --template "{rev}: {node|short} {desc}"
   > EOF
 
   $ rebasewithdag() {
-  >   N=`$PYTHON -c "print($N+1)"`
+  >   N=`"$PYTHON" -c "print($N+1)"`
   >   hg init repo$N && cd repo$N
   >   hg debugdrawdag
   >   hg rebase "$@" > _rebasetmp
   >   r=$?
   >   grep -v 'saved backup bundle' _rebasetmp
   >   [ $r -eq 0 ] && hg tglog
   >   cd ..
   >   return $r
--- a/tests/test-relink.t
+++ b/tests/test-relink.t
@@ -44,17 +44,17 @@ don't sit forever trying to double-lock 
 
   $ hg relink .
   relinking $TESTTMP/repo/.hg/store to $TESTTMP/repo/.hg/store
   there is nothing to relink
 
 
 Test files are read in binary mode
 
-  $ $PYTHON -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\r\nb\n')"
+  $ "$PYTHON" -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\r\nb\n')"
   $ cd ..
 
 
 clone and pull to break links
 
   $ hg clone --pull -r0 repo clone
   adding changesets
   adding manifests
@@ -63,17 +63,17 @@ clone and pull to break links
   new changesets 008c0c271c47
   updating to branch default
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd clone
   $ hg pull -q
   $ echo b >> b
   $ hg ci -m changeb
   created new head
-  $ $PYTHON -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\nb\r\n')"
+  $ "$PYTHON" -c "open('.hg/store/data/dummy.i', 'wb').write(b'a\nb\r\n')"
 
 
 relink
 
 #if no-reposimplestore
 
   $ hg relink --debug --config progress.debug=true | fix_path
   relinking $TESTTMP/repo/.hg/store to $TESTTMP/clone/.hg/store
@@ -93,14 +93,14 @@ relink
   relinking: data/a.i 1/2 files (50.00%)
   not linkable: data/dummy.i
   relinked 1 files (1.36 KB reclaimed)
   $ cd ..
 
 
 check hardlinks
 
-  $ $PYTHON arelinked.py repo/.hg/store/data/a.i clone/.hg/store/data/a.i
+  $ "$PYTHON" arelinked.py repo/.hg/store/data/a.i clone/.hg/store/data/a.i
   repo/.hg/store/data/a.i == clone/.hg/store/data/a.i
-  $ $PYTHON arelinked.py repo/.hg/store/data/b.i clone/.hg/store/data/b.i
+  $ "$PYTHON" arelinked.py repo/.hg/store/data/b.i clone/.hg/store/data/b.i
   repo/.hg/store/data/b.i != clone/.hg/store/data/b.i
 
 #endif
--- a/tests/test-rename-merge2.t
+++ b/tests/test-rename-merge2.t
@@ -42,17 +42,17 @@ args:
   >     # working dir
   >     echo local > rev
   >     if [ "$3" != "" ] ; then $3 ; fi
   > 
   >     # merge
   >     echo "--------------"
   >     echo "test L:$1 R:$2 W:$3 - $4"
   >     echo "--------------"
-  >     hg merge -y --debug --traceback --tool="$PYTHON ../merge"
+  >     hg merge -y --debug --traceback --tool="\"$PYTHON\" ../merge"
   > 
   >     echo "--------------"
   >     hg status -camC -X rev
   > 
   >     hg ci -m "merge"
   > 
   >     echo "--------------"
   >     echo
--- a/tests/test-repair-strip.t
+++ b/tests/test-repair-strip.t
@@ -16,17 +16,17 @@
   >   hg parents
   >   chmod -$3 $4
   >   hg strip $2 2>&1 | sed 's/\(bundle\).*/\1/' | sed 's/Permission denied.*\.hg\/store\/\(.*\)/Permission denied \.hg\/store\/\1/'
   >   echo % after update $1, strip $2
   >   chmod +$3 $4
   >   hg verify
   >   echo % journal contents
   >   if [ -f .hg/store/journal ]; then
-  >       cat .hg/store/journal | $PYTHON $TESTTMP/dumpjournal.py
+  >       cat .hg/store/journal | "$PYTHON" $TESTTMP/dumpjournal.py
   >   else
   >       echo "(no journal)"
   >   fi
   >   ls .hg/store/journal >/dev/null 2>&1 && hg recover
   >   ls .hg/strip-backup/* >/dev/null 2>&1 && hg unbundle -q .hg/strip-backup/*
   >   rm -rf .hg/strip-backup
   > }
 
--- a/tests/test-revert.t
+++ b/tests/test-revert.t
@@ -490,17 +490,17 @@ The files generated have names of the fo
 All known states are not tested yet. See inline documentation for details.
 Special cases from merge and rename are not tested by this section.
 
 Write the python script to disk
 -------------------------------
 
 check list of planned files
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py filelist 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 2
   content1_content1_content1-tracked
   content1_content1_content1-untracked
   content1_content1_content3-tracked
   content1_content1_content3-untracked
   content1_content1_missing-tracked
   content1_content1_missing-untracked
   content1_content2_content1-tracked
   content1_content2_content1-untracked
@@ -545,17 +545,17 @@ Script to make a simple text version of 
 Generate appropriate repo state
 -------------------------------
 
   $ hg init revert-ref
   $ cd revert-ref
 
 Generate base changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove --similarity 0
   adding content1_content1_content1-tracked
   adding content1_content1_content1-untracked
   adding content1_content1_content3-tracked
   adding content1_content1_content3-untracked
   adding content1_content1_missing-tracked
   adding content1_content1_missing-untracked
   adding content1_content2_content1-tracked
@@ -592,17 +592,17 @@ Generate base changeset
   A content1_missing_content3-tracked
   A content1_missing_content3-untracked
   A content1_missing_missing-tracked
   A content1_missing_missing-untracked
   $ hg commit -m 'base'
 
 (create a simple text version of the content)
 
-  $ $PYTHON ../dircontent.py > ../content-base.txt
+  $ "$PYTHON" ../dircontent.py > ../content-base.txt
   $ cat ../content-base.txt
   content1 content1_content1_content1-tracked
   content1 content1_content1_content1-untracked
   content1 content1_content1_content3-tracked
   content1 content1_content1_content3-untracked
   content1 content1_content1_missing-tracked
   content1 content1_content1_missing-untracked
   content1 content1_content2_content1-tracked
@@ -617,17 +617,17 @@ Generate base changeset
   content1 content1_missing_content1-untracked
   content1 content1_missing_content3-tracked
   content1 content1_missing_content3-untracked
   content1 content1_missing_missing-tracked
   content1 content1_missing_missing-untracked
 
 Create parent changeset
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove --similarity 0
   removing content1_missing_content1-tracked
   removing content1_missing_content1-untracked
   removing content1_missing_content3-tracked
   removing content1_missing_content3-untracked
   removing content1_missing_missing-tracked
   removing content1_missing_missing-untracked
   adding missing_content2_content2-tracked
@@ -656,17 +656,17 @@ Create parent changeset
   R content1_missing_content3-tracked
   R content1_missing_content3-untracked
   R content1_missing_missing-tracked
   R content1_missing_missing-untracked
   $ hg commit -m 'parent'
 
 (create a simple text version of the content)
 
-  $ $PYTHON ../dircontent.py > ../content-parent.txt
+  $ "$PYTHON" ../dircontent.py > ../content-parent.txt
   $ cat ../content-parent.txt
   content1 content1_content1_content1-tracked
   content1 content1_content1_content1-untracked
   content1 content1_content1_content3-tracked
   content1 content1_content1_content3-untracked
   content1 content1_content1_missing-tracked
   content1 content1_content1_missing-untracked
   content2 content1_content2_content1-tracked
@@ -681,17 +681,17 @@ Create parent changeset
   content2 missing_content2_content2-untracked
   content2 missing_content2_content3-tracked
   content2 missing_content2_content3-untracked
   content2 missing_content2_missing-tracked
   content2 missing_content2_missing-untracked
 
 Setup working directory
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove --similarity 0
   adding content1_missing_content1-tracked
   adding content1_missing_content1-untracked
   adding content1_missing_content3-tracked
   adding content1_missing_content3-untracked
   adding content1_missing_missing-tracked
   adding content1_missing_missing-untracked
   adding missing_missing_content3-tracked
@@ -749,17 +749,17 @@ Setup working directory
   ! content1_content2_missing-tracked
   ! content1_missing_missing-tracked
   ! missing_content2_missing-tracked
   ! missing_missing_missing-tracked
   ? missing_missing_content3-untracked
 
 (create a simple text version of the content)
 
-  $ $PYTHON ../dircontent.py > ../content-wc.txt
+  $ "$PYTHON" ../dircontent.py > ../content-wc.txt
   $ cat ../content-wc.txt
   content1 content1_content1_content1-tracked
   content1 content1_content1_content1-untracked
   content3 content1_content1_content3-tracked
   content3 content1_content1_content3-untracked
   content1 content1_content2_content1-tracked
   content1 content1_content2_content1-untracked
   content2 content1_content2_content2-tracked
@@ -813,17 +813,17 @@ check revert output
   undeleting missing_content2_content3-untracked
   undeleting missing_content2_missing-untracked
 
 Compare resulting directory with revert target.
 
 The diff is filtered to include change only. The only difference should be
 additional `.orig` backup file when applicable.
 
-  $ $PYTHON ../dircontent.py > ../content-parent-all.txt
+  $ "$PYTHON" ../dircontent.py > ../content-parent-all.txt
   $ cd ..
   $ diff -U 0 -- content-parent.txt content-parent-all.txt | grep _
   +content3 content1_content1_content3-tracked.orig
   +content3 content1_content1_content3-untracked.orig
   +content1 content1_content2_content1-tracked.orig
   +content1 content1_content2_content1-untracked.orig
   +content3 content1_content2_content3-tracked.orig
   +content3 content1_content2_content3-untracked.orig
@@ -870,17 +870,17 @@ check revert output
   undeleting content1_content2_content3-untracked
   undeleting content1_content2_missing-untracked
 
 Compare resulting directory with revert target.
 
 The diff is filtered to include change only. The only difference should be
 additional `.orig` backup file when applicable.
 
-  $ $PYTHON ../dircontent.py > ../content-base-all.txt
+  $ "$PYTHON" ../dircontent.py > ../content-base-all.txt
   $ cd ..
   $ diff -U 0 -- content-base.txt content-base-all.txt | grep _
   +content3 content1_content1_content3-tracked.orig
   +content3 content1_content1_content3-untracked.orig
   +content2 content1_content2_content2-untracked.orig
   +content3 content1_content2_content3-tracked.orig
   +content3 content1_content2_content3-untracked.orig
   +content3 content1_missing_content3-tracked.orig
@@ -897,17 +897,17 @@ Test revert to parent content with expli
 (setup from reference repo)
 
   $ cp -R revert-ref revert-parent-explicit
   $ cd revert-parent-explicit
 
 revert all files individually and check the output
 (output is expected to be different than in the --all case)
 
-  $ for file in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 2`; do
+  $ for file in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 2`; do
   >   echo '### revert for:' $file;
   >   hg revert $file;
   >   echo
   > done
   ### revert for: content1_content1_content1-tracked
   no changes needed to content1_content1_content1-tracked
   
   ### revert for: content1_content1_content1-untracked
@@ -974,33 +974,33 @@ revert all files individually and check 
   
   ### revert for: missing_missing_missing-untracked
   missing_missing_missing-untracked: no such file in rev * (glob)
   
 
 check resulting directory against the --all run
 (There should be no difference)
 
-  $ $PYTHON ../dircontent.py > ../content-parent-explicit.txt
+  $ "$PYTHON" ../dircontent.py > ../content-parent-explicit.txt
   $ cd ..
   $ diff -U 0 -- content-parent-all.txt content-parent-explicit.txt | grep _
   [1]
 
 Test revert to "base" content with explicit file name
 -----------------------------------------------------
 
 (setup from reference repo)
 
   $ cp -R revert-ref revert-base-explicit
   $ cd revert-base-explicit
 
 revert all files individually and check the output
 (output is expected to be different than in the --all case)
 
-  $ for file in `$PYTHON $TESTDIR/generate-working-copy-states.py filelist 2`; do
+  $ for file in `"$PYTHON" $TESTDIR/generate-working-copy-states.py filelist 2`; do
   >   echo '### revert for:' $file;
   >   hg revert $file --rev 'desc(base)';
   >   echo
   > done
   ### revert for: content1_content1_content1-tracked
   no changes needed to content1_content1_content1-tracked
   
   ### revert for: content1_content1_content1-untracked
@@ -1067,17 +1067,17 @@ revert all files individually and check 
   
   ### revert for: missing_missing_missing-untracked
   missing_missing_missing-untracked: no such file in rev * (glob)
   
 
 check resulting directory against the --all run
 (There should be no difference)
 
-  $ $PYTHON ../dircontent.py > ../content-base-explicit.txt
+  $ "$PYTHON" ../dircontent.py > ../content-base-explicit.txt
   $ cd ..
   $ diff -U 0 -- content-base-all.txt content-base-explicit.txt | grep _
   [1]
 
 Revert to an ancestor of P2 during a merge (issue5052)
 -----------------------------------------------------
 
 (prepare the repository)
--- a/tests/test-revset2.t
+++ b/tests/test-revset2.t
@@ -408,24 +408,24 @@ no crash by empty group "()" while optim
       (symbol '0')
       None))
   hg: parse error: missing argument
   [255]
 
 test that chained `or` operations never eat up stack (issue4624)
 (uses `0:1` instead of `0` to avoid future optimization of trivial revisions)
 
-  $ hg log -T '{rev}\n' -r `$PYTHON -c "print '+'.join(['0:1'] * 500)"`
+  $ hg log -T '{rev}\n' -r `"$PYTHON" -c "print '+'.join(['0:1'] * 500)"`
   0
   1
 
 test that repeated `-r` options never eat up stack (issue4565)
 (uses `-r 0::1` to avoid possible optimization at old-style parser)
 
-  $ hg log -T '{rev}\n' `$PYTHON -c "for i in range(500): print '-r 0::1 ',"`
+  $ hg log -T '{rev}\n' `"$PYTHON" -c "for i in range(500): print '-r 0::1 ',"`
   0
   1
 
 check that conversion to only works
   $ try --optimize '::3 - ::1'
   (minus
     (dagrangepre
       (symbol '3'))
@@ -1522,33 +1522,33 @@ unless explicitly specified (issue4682)
 test author/desc/keyword in problematic encoding
 # unicode: cp932:
 # u30A2    0x83 0x41(= 'A')
 # u30C2    0x83 0x61(= 'a')
 
   $ hg init problematicencoding
   $ cd problematicencoding
 
-  $ $PYTHON > setup.sh <<EOF
+  $ "$PYTHON" > setup.sh <<EOF
   > print u'''
   > echo a > text
   > hg add text
   > hg --encoding utf-8 commit -u '\u30A2' -m none
   > echo b > text
   > hg --encoding utf-8 commit -u '\u30C2' -m none
   > echo c > text
   > hg --encoding utf-8 commit -u none -m '\u30A2'
   > echo d > text
   > hg --encoding utf-8 commit -u none -m '\u30C2'
   > '''.encode('utf-8')
   > EOF
   $ sh < setup.sh
 
 test in problematic encoding
-  $ $PYTHON > test.sh <<EOF
+  $ "$PYTHON" > test.sh <<EOF
   > print u'''
   > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30A2)'
   > echo ====
   > hg --encoding cp932 log --template '{rev}\\n' -r 'author(\u30C2)'
   > echo ====
   > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30A2)'
   > echo ====
   > hg --encoding cp932 log --template '{rev}\\n' -r 'desc(\u30C2)'
--- a/tests/test-run-tests.t
+++ b/tests/test-run-tests.t
@@ -1,41 +1,41 @@
 This file tests the behavior of run-tests.py itself.
 
 Avoid interference from actual test env:
 
   $ . "$TESTDIR/helper-runtests.sh"
 
 Smoke test with install
 ============
-  $ $PYTHON $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE -l
+  $ "$PYTHON" $TESTDIR/run-tests.py $HGTEST_RUN_TESTS_PURE -l
   
   # Ran 0 tests, 0 skipped, 0 failed.
 
 Define a helper to avoid the install step
 =============
   $ rt()
   > {
-  >     $PYTHON $TESTDIR/run-tests.py --with-hg=`which hg` "$@"
+  >     "$PYTHON" $TESTDIR/run-tests.py --with-hg=`which hg` "$@"
   > }
 
 error paths
 
 #if symlink
   $ ln -s `which true` hg
-  $ $PYTHON $TESTDIR/run-tests.py --with-hg=./hg
+  $ "$PYTHON" $TESTDIR/run-tests.py --with-hg=./hg
   warning: --with-hg should specify an hg script
   
   # Ran 0 tests, 0 skipped, 0 failed.
   $ rm hg
 #endif
 
 #if execbit
   $ touch hg
-  $ $PYTHON $TESTDIR/run-tests.py --with-hg=./hg
+  $ "$PYTHON" $TESTDIR/run-tests.py --with-hg=./hg
   usage: run-tests.py [options] [tests]
   run-tests.py: error: --with-hg must specify an executable hg script
   [2]
   $ rm hg
 #endif
 
 Features for testing optional lines
 ===================================
@@ -1278,17 +1278,17 @@ Test globbing of local IP addresses
   $ echo 172.16.18.1
   $LOCALIP (glob)
   $ echo dead:beef::1
   $LOCALIP (glob)
 
 Add support for external test formatter
 =======================================
 
-  $ CUSTOM_TEST_RESULT=basic_test_result $PYTHON $TESTDIR/run-tests.py --with-hg=`which hg` "$@" test-success.t test-failure.t
+  $ CUSTOM_TEST_RESULT=basic_test_result "$PYTHON" $TESTDIR/run-tests.py --with-hg=`which hg` "$@" test-success.t test-failure.t
   
   # Ran 2 tests, 0 skipped, 0 failed.
   ON_START! <__main__.TestSuite tests=[<__main__.TTest testMethod=test-failure.t>, <__main__.TTest testMethod=test-success.t>]>
   FAILURE! test-failure.t output changed
   SUCCESS! test-success.t
   ON_END!
 
 Test reusability for third party tools
--- a/tests/test-serve.t
+++ b/tests/test-serve.t
@@ -74,17 +74,17 @@ With --prefix foo/
   % errors
 
 With --prefix /foo/
 
   $ hgserve --prefix /foo/
   listening at http://localhost/foo/ (bound to *$LOCALIP*:HGPORT1) (glob) (?)
   % errors
 
-  $ $PYTHON $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
+  $ "$PYTHON" $RUNTESTDIR/killdaemons.py $DAEMON_PIDS
 
 With out of bounds accesses
 
   $ rm access.log
   $ hg serve -a localhost -p $HGPORT -d --prefix some/dir \
   >    --pid-file=hg.pid -E errors.log
   $ cat hg.pid >> "$DAEMON_PIDS"
 
--- a/tests/test-setdiscovery.t
+++ b/tests/test-setdiscovery.t
@@ -499,19 +499,19 @@ Test actual protocol when pulling one ne
 
 Issue 4438 - test coverage for 3ef893520a85 issues.
 
   $ mkdir issue4438
   $ cd issue4438
 #if false
 generate new bundles:
   $ hg init r1
-  $ for i in `$PYTHON $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
   $ hg clone -q r1 r2
-  $ for i in `$PYTHON $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
   $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
   $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
   $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
 #else
 use existing bundles:
   $ hg init r1
   $ hg -R r1 -q unbundle $TESTDIR/bundles/issue4438-r1.hg
   $ hg -R r1 -q up
--- a/tests/test-simple-update.t
+++ b/tests/test-simple-update.t
@@ -74,17 +74,17 @@ update with worker processes
   $ hg init worker
   $ cd worker
   $ cat <<EOF >> .hg/hgrc
   > [extensions]
   > forceworker = $TESTTMP/forceworker.py
   > [worker]
   > numcpus = 4
   > EOF
-  $ for i in `$PYTHON $TESTDIR/seq.py 1 100`; do
+  $ for i in `"$PYTHON" $TESTDIR/seq.py 1 100`; do
   >   echo $i > $i
   > done
   $ hg ci -qAm 'add 100 files'
 
   $ hg update null
   0 files updated, 0 files merged, 100 files removed, 0 files unresolved
   $ hg update -v | grep 100
   getting 100
--- a/tests/test-sparse-clone.t
+++ b/tests/test-sparse-clone.t
@@ -1,13 +1,13 @@
 test sparse
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$RUNTESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$RUNTESTDIR/dummyssh"
   > username = nobody <no.reply@fb.com>
   > [extensions]
   > sparse=
   > purge=
   > strip=
   > rebase=
   > EOF
 
--- a/tests/test-sparse.t
+++ b/tests/test-sparse.t
@@ -289,25 +289,25 @@ Test status on a file in a subdir
   ? dir1/dir2/file
 
 Mix files and subdirectories, both "glob:" and unprefixed
 
   $ hg debugsparse --reset
   $ touch dir1/notshown
   $ hg commit -A dir1/notshown -m "notshown"
   $ hg debugsparse --include 'dir1/dir2'
-  $ $PYTHON $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
+  $ "$PYTHON" $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
   ./
   ./dir1/
   ./dir1/dir2/
   ./dir1/dir2/file
   ./hide.orig
   $ hg debugsparse --delete 'dir1/dir2'
   $ hg debugsparse --include 'glob:dir1/dir2'
-  $ $PYTHON $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
+  $ "$PYTHON" $TESTDIR/list-tree.py . | egrep -v '\.[\/]\.hg'
   ./
   ./dir1/
   ./dir1/dir2/
   ./dir1/dir2/file
   ./hide.orig
 
 Test that add -s adds dirs to sparse profile
 
--- a/tests/test-split.t
+++ b/tests/test-split.t
@@ -1,12 +1,12 @@
 #testcases obsstore-on obsstore-off
 
   $ cat > $TESTTMP/editor.py <<EOF
-  > #!$PYTHON
+  > #!"$PYTHON"
   > import os
   > import sys
   > path = os.path.join(os.environ['TESTTMP'], 'messages')
   > messages = open(path).read().split('--\n')
   > prompt = open(sys.argv[1]).read()
   > sys.stdout.write(''.join('EDITOR: %s' % l for l in prompt.splitlines(True)))
   > sys.stdout.flush()
   > with open(sys.argv[1], 'w') as f:
--- a/tests/test-ssh-bundle1.t
+++ b/tests/test-ssh-bundle1.t
@@ -390,17 +390,17 @@ parameters:
   abort: no suitable response from remote hg!
   [255]
 
   $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
   remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
   abort: no suitable response from remote hg!
   [255]
 
-  $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" $PYTHON "$TESTDIR/../contrib/hg-ssh"
+  $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" "$PYTHON" "$TESTDIR/../contrib/hg-ssh"
   Illegal command "'hg' serve -R 'a'repo' --stdio": No closing quotation
   [255]
 
 Test hg-ssh in read-only mode:
 
   $ cat > ssh.sh << EOF
   > userhost="\$1"
   > SSH_ORIGINAL_COMMAND="\$2"
--- a/tests/test-ssh-proto.t
+++ b/tests/test-ssh-proto.t
@@ -17,17 +17,17 @@ protocols with inline conditional output
   >   echo "${commands}" | hg --verbose debugwireproto --localssh
   >   echo ""
   >   echo 'testing ssh2'
   >   echo "${commands}" | HGRCPATH=$TESTTMP/hgrc-sshv2 hg --verbose debugwireproto --localssh
   > }
 
   $ cat >> $HGRCPATH << EOF
   > [ui]
-  > ssh = $PYTHON "$TESTDIR/dummyssh"
+  > ssh = "$PYTHON" "$TESTDIR/dummyssh"
   > [devel]
   > debug.peer-request = true
   > [extensions]
   > sshprotoext = $TESTDIR/sshprotoext.py
   > EOF
 
   $ hg init server
   $ cd server
--- a/tests/test-ssh-repoerror.t
+++ b/tests/test-ssh-repoerror.t
@@ -1,15 +1,15 @@
 #require unix-permissions no-root
 
 initial setup
 
   $ cat << EOF >> $HGRCPATH
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > EOF
 
 repository itself is non-readable
 ---------------------------------
 
   $ hg init no-read
   $ hg id ssh://user@dummy/no-read
   000000000000
--- a/tests/test-ssh.t
+++ b/tests/test-ssh.t
@@ -279,17 +279,17 @@ a bad, evil hook that prints to stdout
   > import sys
   > def hook(ui, repo, hooktype, **kwargs):
   >     sys.stdout.write("KABOOM IN PROCESS\n")
   >     sys.stdout.flush()
   > EOF
 
   $ cat <<EOF >> ../remote/.hg/hgrc
   > [hooks]
-  > changegroup.stdout = $PYTHON $TESTTMP/badhook
+  > changegroup.stdout = "$PYTHON" $TESTTMP/badhook
   > changegroup.pystdout = python:$TESTTMP/badpyhook.py:hook
   > EOF
   $ echo r > r
   $ hg ci -A -m z r
 
 push should succeed even though it has an unexpected response
 
   $ hg push
@@ -403,17 +403,17 @@ parameters:
   abort: no suitable response from remote hg!
   [255]
 
   $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
   remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
   abort: no suitable response from remote hg!
   [255]
 
-  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" $PYTHON "$TESTDIR/../contrib/hg-ssh"
+  $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" "$PYTHON" "$TESTDIR/../contrib/hg-ssh"
   Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
   [255]
 
 Test hg-ssh in read-only mode:
 
   $ cat > ssh.sh << EOF
   > userhost="\$1"
   > SSH_ORIGINAL_COMMAND="\$2"
--- a/tests/test-static-http.t
+++ b/tests/test-static-http.t
@@ -4,17 +4,17 @@
   abort: * (glob)
   [255]
   $ test -d copy
   [1]
 
 This server doesn't do range requests so it's basically only good for
 one pull
 
-  $ $PYTHON "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid \
+  $ "$PYTHON" "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid \
   > --logfile server.log
   $ cat dumb.pid >> $DAEMON_PIDS
   $ hg init remote
   $ cd remote
   $ echo foo > bar
   $ echo c2 > '.dotfile with spaces'
   $ hg add
   adding .dotfile with spaces
--- a/tests/test-status-rev.t
+++ b/tests/test-status-rev.t
@@ -1,16 +1,16 @@
 Tests of 'hg status --rev <rev>' to make sure status between <rev> and '.' get
 combined correctly with the dirstate status.
 
   $ hg init
 
 First commit
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 1
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 1
   $ hg addremove --similarity 0
   adding content1_content1_content1-tracked
   adding content1_content1_content1-untracked
   adding content1_content1_content3-tracked
   adding content1_content1_content3-untracked
   adding content1_content1_missing-tracked
   adding content1_content1_missing-untracked
   adding content1_content2_content1-tracked
@@ -26,17 +26,17 @@ First commit
   adding content1_missing_content3-tracked
   adding content1_missing_content3-untracked
   adding content1_missing_missing-tracked
   adding content1_missing_missing-untracked
   $ hg commit -m first
 
 Second commit
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 2
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 2
   $ hg addremove --similarity 0
   removing content1_missing_content1-tracked
   removing content1_missing_content1-untracked
   removing content1_missing_content3-tracked
   removing content1_missing_content3-untracked
   removing content1_missing_missing-tracked
   removing content1_missing_missing-untracked
   adding missing_content2_content2-tracked
@@ -44,17 +44,17 @@ Second commit
   adding missing_content2_content3-tracked
   adding missing_content2_content3-untracked
   adding missing_content2_missing-tracked
   adding missing_content2_missing-untracked
   $ hg commit -m second
 
 Working copy
 
-  $ $PYTHON $TESTDIR/generate-working-copy-states.py state 2 wc
+  $ "$PYTHON" $TESTDIR/generate-working-copy-states.py state 2 wc
   $ hg addremove --similarity 0
   adding content1_missing_content1-tracked
   adding content1_missing_content1-untracked
   adding content1_missing_content3-tracked
   adding content1_missing_content3-untracked
   adding content1_missing_missing-tracked
   adding content1_missing_missing-untracked
   adding missing_missing_content3-tracked
--- a/tests/test-subrepo-svn.t
+++ b/tests/test-subrepo-svn.t
@@ -1,15 +1,15 @@
 #require svn15
 
   $ SVNREPOPATH=`pwd`/svn-repo
 #if windows
-  $ SVNREPOURL=file:///`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file:///`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #else
-  $ SVNREPOURL=file://`$PYTHON -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
+  $ SVNREPOURL=file://`"$PYTHON" -c "import urllib, sys; sys.stdout.write(urllib.quote(sys.argv[1]))" "$SVNREPOPATH"`
 #endif
 
   $ filter_svn_output () {
   >     egrep -v 'Committing|Transmitting|Updating|(^$)' || true
   > }
 
 create subversion repo
 
@@ -242,17 +242,17 @@ debugsub in clone
    source   file:/*/$TESTTMP/svn-repo/src (glob)
    revision 3
   path subdir/s
    source   file:/*/$TESTTMP/svn-repo/src (glob)
    revision 2
 
 verify subrepo is contained within the repo directory
 
-  $ $PYTHON -c "import os.path; print os.path.exists('s')"
+  $ "$PYTHON" -c "import os.path; print os.path.exists('s')"
   True
 
 update to nullrev (must delete the subrepo)
 
   $ hg up null
   0 files updated, 0 files merged, 3 files removed, 0 files unresolved
   $ ls
 
--- a/tests/test-tag.t
+++ b/tests/test-tag.t
@@ -225,29 +225,29 @@ cloning local tags
   hook: +A acb14030fe0a21b60322c440ad2d20cf7685a376 bleah
   $ hg -R test3 parents --style=compact
 
   $ cd test
 
 Issue601: hg tag doesn't do the right thing if .hgtags or localtags
 doesn't end with EOL
 
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > f = open('.hg/localtags'); last = f.readlines()[-1][:-1]; f.close()
   > f = open('.hg/localtags', 'w'); f.write(last); f.close()
   > EOF
   $ cat .hg/localtags; echo
   acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
   $ hg tag -l localnewline
   $ cat .hg/localtags; echo
   acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
   c2899151f4e76890c602a2597a650a72666681bf localnewline
   
 
-  $ $PYTHON << EOF
+  $ "$PYTHON" << EOF
   > f = open('.hgtags'); last = f.readlines()[-1][:-1]; f.close()
   > f = open('.hgtags', 'w'); f.write(last); f.close()
   > EOF
   $ hg ci -m'broken manual edit of .hgtags'
   $ cat .hgtags; echo
   acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
   $ hg tag newline
   hook: tag changes detected
--- a/tests/test-template-functions.t
+++ b/tests/test-template-functions.t
@@ -1388,17 +1388,17 @@ json filter should escape HTML tags so t
 
   $ hg log -T "{'<foo@example.org>'|json}\n" -R a -l1
   "\u003cfoo@example.org\u003e"
 
 Set up repository for non-ascii encoding tests:
 
   $ hg init nonascii
   $ cd nonascii
-  $ $PYTHON <<EOF
+  $ "$PYTHON" <<EOF
   > open('latin1', 'wb').write(b'\xe9')
   > open('utf-8', 'wb').write(b'\xc3\xa9')
   > EOF
   $ HGENCODING=utf-8 hg branch -q `cat utf-8`
   $ HGENCODING=utf-8 hg ci -qAm "non-ascii branch: `cat utf-8`" utf-8
 
 json filter should try round-trip conversion to utf-8:
 
--- a/tests/test-tools.t
+++ b/tests/test-tools.t
@@ -46,20 +46,20 @@ Tests of the file helper tool
   foo: sha256=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
 
 #if symlink
   $ f foo --mode
   foo: mode=644
 #endif
 
 #if no-windows
-  $ $PYTHON $TESTDIR/seq.py 10 > bar
+  $ "$PYTHON" $TESTDIR/seq.py 10 > bar
 #else
 Convert CRLF -> LF for consistency
-  $ $PYTHON $TESTDIR/seq.py 10 | sed "s/$//" > bar
+  $ "$PYTHON" $TESTDIR/seq.py 10 | sed "s/$//" > bar
 #endif
 
 #if unix-permissions symlink
   $ chmod +x bar
   $ f bar --newer foo --mode --type --size --dump --links --bytes 7
   bar: file, size=21, mode=755, links=1, newer than foo
   >>>
   1
--- a/tests/test-transplant.t
+++ b/tests/test-transplant.t
@@ -753,17 +753,17 @@ test with a win32ext like setup (differi
   $ echo b >> b
   $ hg ci -m changeb
   $ cd ..
 
   $ hg init twin2
   $ cd twin2
   $ echo '[patch]' >> .hg/hgrc
   $ echo 'eol = crlf' >> .hg/hgrc
-  $ $PYTHON -c "open('b', 'wb').write(b'b\r\nb\r\n')"
+  $ "$PYTHON" -c "open('b', 'wb').write(b'b\r\nb\r\n')"
   $ hg ci -Am addb
   adding b
   $ hg transplant -s ../twin1 tip
   searching for changes
   warning: repository is unrelated
   applying 2e849d776c17
   2e849d776c17 transplanted to 8e65bebc063e
   $ cat b
--- a/tests/test-treemanifest.t
+++ b/tests/test-treemanifest.t
@@ -1,11 +1,11 @@
   $ cat << EOF >> $HGRCPATH
   > [ui]
-  > ssh=$PYTHON "$TESTDIR/dummyssh"
+  > ssh="$PYTHON" "$TESTDIR/dummyssh"
   > EOF
 
 Set up repo
 
   $ hg --config experimental.treemanifest=True init repo
   $ cd repo
 
 Requirements get set on init
--- a/tests/test-walk.t
+++ b/tests/test-walk.t
@@ -598,23 +598,23 @@ Test patterns:
   <patternmatcher patterns='(?:ignored(?:/|$))'>
   $ hg debugwalk -v ignored/file
   * matcher:
   <patternmatcher patterns='(?:ignored/file(?:/|$))'>
   f  ignored/file  ignored/file  exact
 
 Test listfile and listfile0
 
-  $ $PYTHON -c "open('listfile0', 'wb').write(b'fenugreek\0new\0')"
+  $ "$PYTHON" -c "open('listfile0', 'wb').write(b'fenugreek\0new\0')"
   $ hg debugwalk -v -I 'listfile0:listfile0'
   * matcher:
   <includematcher includes='(?:fenugreek(?:/|$)|new(?:/|$))'>
   f  fenugreek  fenugreek
   f  new        new
-  $ $PYTHON -c "open('listfile', 'wb').write(b'fenugreek\nnew\r\nmammals/skunk\n')"
+  $ "$PYTHON" -c "open('listfile', 'wb').write(b'fenugreek\nnew\r\nmammals/skunk\n')"
   $ hg debugwalk -v -I 'listfile:listfile'
   * matcher:
   <includematcher includes='(?:fenugreek(?:/|$)|new(?:/|$)|mammals/skunk(?:/|$))'>
   f  fenugreek      fenugreek
   f  mammals/skunk  mammals/skunk
   f  new            new
 
   $ cd ..
@@ -639,14 +639,14 @@ Test split patterns on overflow
 
   $ cd t
   $ echo fennel > overflow.list
   $ cat >> printnum.py <<EOF
   > from __future__ import print_function
   > for i in range(20000 // 100):
   >   print('x' * 100)
   > EOF
-  $ $PYTHON printnum.py >> overflow.list
+  $ "$PYTHON" printnum.py >> overflow.list
   $ echo fenugreek >> overflow.list
   $ hg debugwalk 'listfile:overflow.list' 2>&1 | egrep -v '^xxx'
   f  fennel     fennel     exact
   f  fenugreek  fenugreek  exact
   $ cd ..
--- a/tests/test-win32text.t
+++ b/tests/test-win32text.t
@@ -23,17 +23,17 @@
 commit should succeed
 
   $ hg ci -m 1
 
   $ hg clone . ../zoz
   updating to branch default
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cp .hg/hgrc ../zoz/.hg
-  $ $PYTHON unix2dos.py f
+  $ "$PYTHON" unix2dos.py f
 
 commit should fail
 
   $ hg ci -m 2.1
   attempt to commit or push text file(s) using CRLF line endings
   in f583ea08d42a: f
   transaction abort!
   rollback completed
@@ -97,33 +97,33 @@ push should succeed
   adding manifests
   adding file changes
   added 3 changesets with 3 changes to 2 files
 
 and now for something completely different
 
   $ mkdir d
   $ echo hello > d/f2
-  $ $PYTHON unix2dos.py d/f2
+  $ "$PYTHON" unix2dos.py d/f2
   $ hg add d/f2
   $ hg ci -m 3
   attempt to commit or push text file(s) using CRLF line endings
   in 053ba1a3035a: d/f2
   transaction abort!
   rollback completed
   abort: pretxncommit.crlf hook failed
   [255]
   $ hg revert -a
   forgetting d/f2
   $ rm d/f2
 
   $ hg rem f
   $ hg ci -m 4
 
-  $ $PYTHON -c 'open("bin", "wb").write(b"hello\x00\x0D\x0A")'
+  $ "$PYTHON" -c 'open("bin", "wb").write(b"hello\x00\x0D\x0A")'
   $ hg add bin
   $ hg ci -m 5
   $ hg log -v
   changeset:   5:f0b1c8d75fce
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
   files:       bin
@@ -176,17 +176,17 @@ and now for something completely differe
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ for x in a b c d; do echo content > dupe/$x; done
   $ hg -R dupe add
   adding dupe/a
   adding dupe/b
   adding dupe/c
   adding dupe/d
-  $ $PYTHON unix2dos.py dupe/b dupe/c dupe/d
+  $ "$PYTHON" unix2dos.py dupe/b dupe/c dupe/d
   $ hg -R dupe ci -m a dupe/a
   $ hg -R dupe ci -m b/c dupe/[bc]
   $ hg -R dupe ci -m d dupe/d
   $ hg -R dupe log -v
   changeset:   8:67ac5962ab43
   tag:         tip
   user:        test
   date:        Thu Jan 01 00:00:00 1970 +0000
@@ -337,17 +337,17 @@ and now for something completely differe
   date:        Thu Jan 01 00:00:00 1970 +0000
   files:       f
   description:
   1
   
   
   $ rm .hg/hgrc
   $ (echo some; echo text) > f3
-  $ $PYTHON -c 'open("f4.bat", "wb").write(b"rem empty\x0D\x0A")'
+  $ "$PYTHON" -c 'open("f4.bat", "wb").write(b"rem empty\x0D\x0A")'
   $ hg add f3 f4.bat
   $ hg ci -m 6
   $ cat bin
   hello\x00\r (esc)
   $ cat f3
   some
   text
   $ cat f4.bat
@@ -390,17 +390,17 @@ Disable warning:
   $ cat bin
   hello\x00\r (esc)
   $ cat f3
   some\r (esc)
   text\r (esc)
   $ cat f4.bat
   rem empty\r (esc)
 
-  $ $PYTHON -c 'open("f5.sh", "wb").write(b"# empty\x0D\x0A")'
+  $ "$PYTHON" -c 'open("f5.sh", "wb").write(b"# empty\x0D\x0A")'
   $ hg add f5.sh
   $ hg ci -m 7
   $ cat f5.sh
   # empty\r (esc)
   $ hg cat f5.sh
   # empty
   $ echo '% just linefeed' > linefeed
   $ hg ci -qAm 8 linefeed