util.system: Use subprocess instead of os.system
subprocess allows the environment and working directory to be specified
directly, so the hacks for making temporary changes while forking is no longer
necessary.
This also fixes failures on solaris where the temporary changes can't be undone
because there is no unsetenv.
--- a/mercurial/posix.py Wed Sep 23 02:31:09 2009 -0500
+++ b/mercurial/posix.py Sun Sep 20 22:19:18 2009 +0200
@@ -165,17 +165,11 @@
return inst.errno != errno.ESRCH
def explain_exit(code):
- """return a 2-tuple (desc, code) describing a process's status"""
- if os.WIFEXITED(code):
- val = os.WEXITSTATUS(code)
- return _("exited with status %d") % val, val
- elif os.WIFSIGNALED(code):
- val = os.WTERMSIG(code)
- return _("killed by signal %d") % val, val
- elif os.WIFSTOPPED(code):
- val = os.WSTOPSIG(code)
- return _("stopped by signal %d") % val, val
- raise ValueError(_("invalid exit code"))
+ """return a 2-tuple (desc, code) describing a subprocess status
+ (codes from kill are negative - not os.system/wait encoding)"""
+ if code >= 0:
+ return _("exited with status %d") % code, code
+ return _("killed by signal %d") % -code, -code
def isowner(st):
"""Return True if the stat object st is from the current user."""
--- a/mercurial/util.py Wed Sep 23 02:31:09 2009 -0500
+++ b/mercurial/util.py Sun Sep 20 22:19:18 2009 +0200
@@ -357,41 +357,26 @@
if val is True:
return '1'
return str(val)
- oldenv = {}
- for k in environ:
- oldenv[k] = os.environ.get(k)
- if cwd is not None:
- oldcwd = os.getcwd()
origcmd = cmd
if os.name == 'nt':
cmd = '"%s"' % cmd
- try:
- for k, v in environ.iteritems():
- os.environ[k] = py2shell(v)
- os.environ['HG'] = hgexecutable()
- if cwd is not None and oldcwd != cwd:
- os.chdir(cwd)
- rc = os.system(cmd)
- if sys.platform == 'OpenVMS' and rc & 1:
- rc = 0
- if rc and onerr:
- errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
- explain_exit(rc)[0])
- if errprefix:
- errmsg = '%s: %s' % (errprefix, errmsg)
- try:
- onerr.warn(errmsg + '\n')
- except AttributeError:
- raise onerr(errmsg)
- return rc
- finally:
- for k, v in oldenv.iteritems():
- if v is None:
- del os.environ[k]
- else:
- os.environ[k] = v
- if cwd is not None and oldcwd != cwd:
- os.chdir(oldcwd)
+ env = dict(os.environ)
+ env.update((k, py2shell(v)) for k, v in environ.iteritems())
+ env['HG'] = hgexecutable()
+ rc = subprocess.call(cmd, shell=True, close_fds=closefds,
+ env=env, cwd=cwd)
+ if sys.platform == 'OpenVMS' and rc & 1:
+ rc = 0
+ if rc and onerr:
+ errmsg = '%s %s' % (os.path.basename(origcmd.split(None, 1)[0]),
+ explain_exit(rc)[0])
+ if errprefix:
+ errmsg = '%s: %s' % (errprefix, errmsg)
+ try:
+ onerr.warn(errmsg + '\n')
+ except AttributeError:
+ raise onerr(errmsg)
+ return rc
def checksignature(func):
'''wrap a function with code to check for calling errors'''