changeset 9517:4368f582c806

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.
author Mads Kiilerich <mads@kiilerich.com>
date Sun, 20 Sep 2009 22:19:18 +0200
parents f8048c334066
children bc19a0b04e83
files mercurial/posix.py mercurial/util.py
diffstat 2 files changed, 22 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- 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'''