[PATCH 2 of 2 STABLE] convert: use subprocess for all commandline calls

Patrick Mezard patrick at mezard.eu
Fri Aug 3 20:12:40 UTC 2012


# HG changeset patch
# User Patrick Mezard <patrick at mezard.eu>
# Date 1344022653 -7200
# Branch stable
# Node ID 5277fbc8821365891af1ea26e8809e0f9a6637a2
# Parent  ce2cfb0d86bd4c54e935e76ac1b8043ba9aecb51
convert: use subprocess for all commandline calls

Avoid mixing popen and subprocess calls, it simplifies the command line
generation and quoting issues with redirections.

In practice, it fixes the subversion sink on Windows and probably helps
with monotone and darcs sources.

diff --git a/hgext/convert/common.py b/hgext/convert/common.py
--- a/hgext/convert/common.py
+++ b/hgext/convert/common.py
@@ -5,8 +5,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import base64, errno
-import os
+import base64, errno, subprocess, os
 import cPickle as pickle
 from mercurial import util
 from mercurial.i18n import _
@@ -260,7 +259,7 @@
     def postrun(self):
         pass
 
-    def _cmdline(self, cmd, closestdin, *args, **kwargs):
+    def _cmdline(self, cmd, *args, **kwargs):
         cmdline = [self.command, cmd] + list(args)
         for k, v in kwargs.iteritems():
             if len(k) == 1:
@@ -277,19 +276,22 @@
         cmdline = [util.shellquote(arg) for arg in cmdline]
         if not self.ui.debugflag:
             cmdline += ['2>', util.nulldev]
-        if closestdin:
-            cmdline += ['<', util.nulldev]
         cmdline = ' '.join(cmdline)
         return cmdline
 
     def _run(self, cmd, *args, **kwargs):
-        return self._dorun(util.popen, cmd, True, *args, **kwargs)
+        def popen(cmdline):
+            p = subprocess.Popen(cmdline, shell=True, bufsize=-1,
+                    close_fds=util.closefds,
+                    stdout=subprocess.PIPE)
+            return p
+        return self._dorun(popen, cmd, *args, **kwargs)
 
     def _run2(self, cmd, *args, **kwargs):
-        return self._dorun(util.popen2, cmd, False, *args, **kwargs)
+        return self._dorun(util.popen2, cmd, *args, **kwargs)
 
-    def _dorun(self, openfunc, cmd, closestdin, *args, **kwargs):
-        cmdline = self._cmdline(cmd, closestdin, *args, **kwargs)
+    def _dorun(self, openfunc, cmd,  *args, **kwargs):
+        cmdline = self._cmdline(cmd, *args, **kwargs)
         self.ui.debug('running: %s\n' % (cmdline,))
         self.prerun()
         try:
@@ -298,16 +300,17 @@
             self.postrun()
 
     def run(self, cmd, *args, **kwargs):
-        fp = self._run(cmd, *args, **kwargs)
-        output = fp.read()
+        p = self._run(cmd, *args, **kwargs)
+        output = p.communicate()[0]
         self.ui.debug(output)
-        return output, fp.close()
+        return output, p.returncode
 
     def runlines(self, cmd, *args, **kwargs):
-        fp = self._run(cmd, *args, **kwargs)
-        output = fp.readlines()
+        p = self._run(cmd, *args, **kwargs)
+        output = p.stdout.readlines()
+        p.wait()
         self.ui.debug(''.join(output))
-        return output, fp.close()
+        return output, p.returncode
 
     def checkexit(self, status, output=''):
         if status:
diff --git a/hgext/convert/darcs.py b/hgext/convert/darcs.py
--- a/hgext/convert/darcs.py
+++ b/hgext/convert/darcs.py
@@ -104,9 +104,10 @@
         # possible, etree will still raise an exception if any
         # non-printable characters are in the XML changelog.
         parser = XMLParser(encoding='latin-1')
-        fp = self._run(cmd, **kwargs)
-        etree.parse(fp, parser=parser)
-        self.checkexit(fp.close())
+        p = self._run(cmd, **kwargs)
+        etree.parse(p.stdout, parser=parser)
+        p.wait()
+        self.checkexit(p.returncode)
         return etree.getroot()
 
     def format(self):



More information about the Mercurial-devel mailing list