# HG changeset patch # User Matt Harbison # Date 2018-09-23 04:47:04 # Node ID c31ce080eb75fa379031e4ce3f1457f91770f180 # Parent 874712506b07244de1cf90112a1ead6888074dc7 py3: convert arguments, cwd and env to native strings when spawning subprocess This keeps Windows happy. diff --git a/hgext/convert/common.py b/hgext/convert/common.py --- a/hgext/convert/common.py +++ b/hgext/convert/common.py @@ -402,7 +402,8 @@ class commandline(object): def _run(self, cmd, *args, **kwargs): def popen(cmdline): - p = subprocess.Popen(cmdline, shell=True, bufsize=-1, + p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmdline), + shell=True, bufsize=-1, close_fds=procutil.closefds, stdout=subprocess.PIPE) return p diff --git a/hgext/convert/gnuarch.py b/hgext/convert/gnuarch.py --- a/hgext/convert/gnuarch.py +++ b/hgext/convert/gnuarch.py @@ -17,6 +17,7 @@ from mercurial.i18n import _ from mercurial import ( encoding, error, + pycompat, ) from mercurial.utils import ( dateutil, @@ -201,7 +202,7 @@ class gnuarch_source(common.converter_so cmdline += ['>', os.devnull, '2>', os.devnull] cmdline = procutil.quotecommand(' '.join(cmdline)) self.ui.debug(cmdline, '\n') - return os.system(cmdline) + return os.system(pycompat.rapply(procutil.tonativestr, cmdline)) def _update(self, rev): self.ui.debug('applying revision %s...\n' % rev) diff --git a/hgext/factotum.py b/hgext/factotum.py --- a/hgext/factotum.py +++ b/hgext/factotum.py @@ -49,6 +49,9 @@ from __future__ import absolute_import import os from mercurial.i18n import _ +from mercurial.utils import ( + procutil, +) from mercurial import ( error, httpconnection, @@ -83,7 +86,7 @@ def auth_getkey(self, params): if 'user=' not in params: params = '%s user?' % params params = '%s !password?' % params - os.system("%s -g '%s'" % (_executable, params)) + os.system(procutil.tonativestr("%s -g '%s'" % (_executable, params))) def auth_getuserpasswd(self, getkey, params): params = 'proto=pass %s' % params diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -58,6 +58,10 @@ from mercurial.i18n import _ from mercurial.node import nullrev from mercurial.node import wdirrev +from mercurial.utils import ( + procutil, +) + from mercurial import ( cmdutil, context, @@ -448,9 +452,9 @@ def fixfile(ui, opts, fixers, fixctx, pa continue ui.debug('subprocess: %s\n' % (command,)) proc = subprocess.Popen( - command, + pycompat.rapply(procutil.tonativestr, command), shell=True, - cwd='/', + cwd=procutil.tonativestr(b'/'), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) diff --git a/hgext/fsmonitor/pywatchman/__init__.py b/hgext/fsmonitor/pywatchman/__init__.py --- a/hgext/fsmonitor/pywatchman/__init__.py +++ b/hgext/fsmonitor/pywatchman/__init__.py @@ -48,6 +48,14 @@ try: except ImportError: from . import pybser as bser +from mercurial.utils import ( + procutil, +) + +from mercurial import ( + pycompat, +) + from . import ( capabilities, compat, @@ -580,7 +588,8 @@ class CLIProcessTransport(Transport): '--no-pretty', '-j', ] - self.proc = subprocess.Popen(args, + self.proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr, + args), stdin=subprocess.PIPE, stdout=subprocess.PIPE) return self.proc @@ -822,7 +831,8 @@ class client(object): startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW args['startupinfo'] = startupinfo - p = subprocess.Popen(cmd, **args) + p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd), + **args) except OSError as e: raise WatchmanError('"watchman" executable not in PATH (%s)' % e) diff --git a/hgext/infinitepush/__init__.py b/hgext/infinitepush/__init__.py --- a/hgext/infinitepush/__init__.py +++ b/hgext/infinitepush/__init__.py @@ -1182,5 +1182,6 @@ def _asyncsavemetadata(root, nodes): cmdline = [util.hgexecutable(), 'debugfillinfinitepushmetadata', '-R', root] + nodesargs # Process will run in background. We don't care about the return code - subprocess.Popen(cmdline, close_fds=True, shell=False, + subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmdline), + close_fds=True, shell=False, stdin=devnull, stdout=devnull, stderr=devnull) diff --git a/hgext/infinitepush/store.py b/hgext/infinitepush/store.py --- a/hgext/infinitepush/store.py +++ b/hgext/infinitepush/store.py @@ -11,6 +11,13 @@ import os import subprocess import tempfile +from mercurial import ( + pycompat, +) +from mercurial.utils import ( + procutil, +) + NamedTemporaryFile = tempfile.NamedTemporaryFile class BundleWriteException(Exception): @@ -111,7 +118,8 @@ class externalbundlestore(abstractbundle def _call_binary(self, args): p = subprocess.Popen( - args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + pycompat.rapply(procutil.tonativestr, args), + stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() returncode = p.returncode diff --git a/hgext/logtoprocess.py b/hgext/logtoprocess.py --- a/hgext/logtoprocess.py +++ b/hgext/logtoprocess.py @@ -44,6 +44,10 @@ from mercurial import ( pycompat, ) +from mercurial.utils import ( + procutil, +) + # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should # be specifying the version(s) of Mercurial they are tested with, or @@ -62,7 +66,8 @@ def uisetup(ui): # we can't use close_fds *and* redirect stdin. I'm not sure that we # need to because the detached process has no console connection. subprocess.Popen( - script, shell=True, env=env, close_fds=True, + pycompat.rapply(procutil.tonativestr, script), + shell=True, env=procutil.tonativeenv(env), close_fds=True, creationflags=_creationflags) else: def runshellcommand(script, env): @@ -82,7 +87,9 @@ def uisetup(ui): # connect stdin to devnull to make sure the subprocess can't # muck up that stream for mercurial. subprocess.Popen( - script, shell=True, stdin=open(os.devnull, 'r'), env=env, + pycompat.rapply(procutil.tonativestr, script), + shell=True, stdin=open(os.devnull, 'r'), + env=procutil.tonativeenv(env), close_fds=True, **newsession) finally: # mission accomplished, this child needs to exit and not diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -3074,7 +3074,8 @@ def debugwireproto(ui, repo, path=None, '-R', repo.root, 'debugserve', '--sshstdio', ] - proc = subprocess.Popen(args, stdin=subprocess.PIPE, + proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr, args), + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0) diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py --- a/mercurial/scmutil.py +++ b/mercurial/scmutil.py @@ -1339,9 +1339,11 @@ def extdatasource(repo, source): if spec.startswith("shell:"): # external commands should be run relative to the repo root cmd = spec[6:] - proc = subprocess.Popen(cmd, shell=True, bufsize=-1, + proc = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd), + shell=True, bufsize=-1, close_fds=procutil.closefds, - stdout=subprocess.PIPE, cwd=repo.root) + stdout=subprocess.PIPE, + cwd=procutil.tonativestr(repo.root)) src = proc.stdout else: # treat as a URL or file diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -951,9 +951,11 @@ class svnsubrepo(abstractsubrepo): env['LANG'] = lc_all del env['LC_ALL'] env['LC_MESSAGES'] = 'C' - p = subprocess.Popen(cmd, bufsize=-1, close_fds=procutil.closefds, + p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, cmd), + bufsize=-1, close_fds=procutil.closefds, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - universal_newlines=True, env=env, **extrakw) + universal_newlines=True, + env=procutil.tonativeenv(env), **extrakw) stdout, stderr = p.communicate() stderr = stderr.strip() if not failok: @@ -1268,8 +1270,12 @@ class gitsubrepo(abstractsubrepo): # insert the argument in the front, # the end of git diff arguments is used for paths commands.insert(1, '--color') - p = subprocess.Popen([self._gitexecutable] + commands, bufsize=-1, - cwd=cwd, env=env, close_fds=procutil.closefds, + p = subprocess.Popen(pycompat.rapply(procutil.tonativestr, + [self._gitexecutable] + commands), + bufsize=-1, + cwd=pycompat.rapply(procutil.tonativestr, cwd), + env=procutil.tonativeenv(env), + close_fds=procutil.closefds, stdout=subprocess.PIPE, stderr=errpipe) if stream: return p.stdout, None diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py --- a/mercurial/utils/procutil.py +++ b/mercurial/utils/procutil.py @@ -120,13 +120,15 @@ def popen(cmd, mode='rb', bufsize=-1): raise error.ProgrammingError('unsupported mode: %r' % mode) def _popenreader(cmd, bufsize): - p = subprocess.Popen(quotecommand(cmd), shell=True, bufsize=bufsize, + p = subprocess.Popen(tonativestr(quotecommand(cmd)), + shell=True, bufsize=bufsize, close_fds=closefds, stdout=subprocess.PIPE) return _pfile(p, p.stdout) def _popenwriter(cmd, bufsize): - p = subprocess.Popen(quotecommand(cmd), shell=True, bufsize=bufsize, + p = subprocess.Popen(tonativestr(quotecommand(cmd)), + shell=True, bufsize=bufsize, close_fds=closefds, stdin=subprocess.PIPE) return _pfile(p, p.stdin) @@ -135,10 +137,11 @@ def popen2(cmd, env=None): # Setting bufsize to -1 lets the system decide the buffer size. # The default for bufsize is 0, meaning unbuffered. This leads to # poor performance on Mac OS X: http://bugs.python.org/issue4194 - p = subprocess.Popen(cmd, shell=True, bufsize=-1, + p = subprocess.Popen(pycompat.rapply(tonativestr, cmd), + shell=True, bufsize=-1, close_fds=closefds, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - env=env) + env=tonativeenv(env)) return p.stdin, p.stdout def popen3(cmd, env=None): @@ -146,16 +149,18 @@ def popen3(cmd, env=None): return stdin, stdout, stderr def popen4(cmd, env=None, bufsize=-1): - p = subprocess.Popen(cmd, shell=True, bufsize=bufsize, + p = subprocess.Popen(pycompat.rapply(tonativestr, cmd), + shell=True, bufsize=bufsize, close_fds=closefds, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - env=env) + env=tonativeenv(env)) return p.stdin, p.stdout, p.stderr, p def pipefilter(s, cmd): '''filter string S through command CMD, returning its output''' - p = subprocess.Popen(cmd, shell=True, close_fds=closefds, + p = subprocess.Popen(pycompat.rapply(tonativestr, cmd), + shell=True, close_fds=closefds, stdin=subprocess.PIPE, stdout=subprocess.PIPE) pout, perr = p.communicate(s) return pout @@ -346,11 +351,16 @@ def system(cmd, environ=None, cwd=None, cmd = quotecommand(cmd) env = shellenviron(environ) if out is None or isstdout(out): - rc = subprocess.call(cmd, shell=True, close_fds=closefds, - env=env, cwd=cwd) + rc = subprocess.call(pycompat.rapply(tonativestr, cmd), + shell=True, close_fds=closefds, + env=tonativeenv(env), + cwd=pycompat.rapply(tonativestr, cwd)) else: - proc = subprocess.Popen(cmd, shell=True, close_fds=closefds, - env=env, cwd=cwd, stdout=subprocess.PIPE, + proc = subprocess.Popen(pycompat.rapply(tonativestr, cmd), + shell=True, close_fds=closefds, + env=tonativeenv(env), + cwd=pycompat.rapply(tonativestr, cwd), + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) for line in iter(proc.stdout.readline, ''): out.write(line)