changeset 40497:3fbfbc8c9f82

remotefilelog: transplant runbgcommand to procutil While cleaning up the deprecated runshellcommand I noticed a near-clone of this in logtoprocess, so I'm standardizing on what appears to be the newer one by moving it to procutil. Differential Revision: https://phab.mercurial-scm.org/D4938
author Augie Fackler <augie@google.com>
date Wed, 03 Oct 2018 14:01:04 -0400
parents 60eb35b0c11c
children 8fab95aa5280
files hgext/remotefilelog/extutil.py hgext/remotefilelog/repack.py hgext/remotefilelog/shallowrepo.py mercurial/utils/procutil.py
diffstat 4 files changed, 74 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/remotefilelog/extutil.py	Wed Oct 03 13:54:45 2018 -0400
+++ b/hgext/remotefilelog/extutil.py	Wed Oct 03 14:01:04 2018 -0400
@@ -10,88 +10,15 @@
 import contextlib
 import errno
 import os
-import subprocess
 import time
 
 from mercurial import (
     error,
     lock as lockmod,
-    pycompat,
     util,
     vfs as vfsmod,
 )
 
-if pycompat.iswindows:
-    # no fork on Windows, but we can create a detached process
-    # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
-    # No stdlib constant exists for this value
-    DETACHED_PROCESS = 0x00000008
-    _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP
-
-    def runbgcommand(script, env, shell=False, stdout=None, stderr=None):
-        '''Spawn a command without waiting for it to finish.'''
-        # 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=shell, env=env, close_fds=True,
-            creationflags=_creationflags, stdout=stdout, stderr=stderr)
-else:
-    def runbgcommand(cmd, env, shell=False, stdout=None, stderr=None):
-        '''Spawn a command without waiting for it to finish.'''
-        # double-fork to completely detach from the parent process
-        # based on http://code.activestate.com/recipes/278731
-        pid = os.fork()
-        if pid:
-            # Parent process
-            (_pid, status) = os.waitpid(pid, 0)
-            if os.WIFEXITED(status):
-                returncode = os.WEXITSTATUS(status)
-            else:
-                returncode = -os.WTERMSIG(status)
-            if returncode != 0:
-                # The child process's return code is 0 on success, an errno
-                # value on failure, or 255 if we don't have a valid errno
-                # value.
-                #
-                # (It would be slightly nicer to return the full exception info
-                # over a pipe as the subprocess module does.  For now it
-                # doesn't seem worth adding that complexity here, though.)
-                if returncode == 255:
-                    returncode = errno.EINVAL
-                raise OSError(returncode, 'error running %r: %s' %
-                              (cmd, os.strerror(returncode)))
-            return
-
-        returncode = 255
-        try:
-            # Start a new session
-            os.setsid()
-
-            stdin = open(os.devnull, 'r')
-            if stdout is None:
-                stdout = open(os.devnull, 'w')
-            if stderr is None:
-                stderr = open(os.devnull, 'w')
-
-            # connect stdin to devnull to make sure the subprocess can't
-            # muck up that stream for mercurial.
-            subprocess.Popen(
-                cmd, shell=shell, env=env, close_fds=True,
-                stdin=stdin, stdout=stdout, stderr=stderr)
-            returncode = 0
-        except EnvironmentError as ex:
-            returncode = (ex.errno & 0xff)
-            if returncode == 0:
-                # This shouldn't happen, but just in case make sure the
-                # return code is never 0 here.
-                returncode = 255
-        except Exception:
-            returncode = 255
-        finally:
-            # mission accomplished, this child needs to exit and not
-            # continue the hg process here.
-            os._exit(returncode)
-
 @contextlib.contextmanager
 def flock(lockpath, description, timeout=-1):
     """A flock based lock object. Currently it is always non-blocking.
--- a/hgext/remotefilelog/repack.py	Wed Oct 03 13:54:45 2018 -0400
+++ b/hgext/remotefilelog/repack.py	Wed Oct 03 14:01:04 2018 -0400
@@ -50,7 +50,7 @@
     if packsonly:
         cmd.append('--packsonly')
     repo.ui.warn(msg)
-    extutil.runbgcommand(cmd, encoding.environ)
+    procutil.runbgcommand(cmd, encoding.environ)
 
 def fullrepack(repo, options=None):
     """If ``packsonly`` is True, stores creating only loose objects are skipped.
--- a/hgext/remotefilelog/shallowrepo.py	Wed Oct 03 13:54:45 2018 -0400
+++ b/hgext/remotefilelog/shallowrepo.py	Wed Oct 03 14:01:04 2018 -0400
@@ -25,7 +25,6 @@
     constants,
     contentstore,
     datapack,
-    extutil,
     fileserverclient,
     historypack,
     metadatastore,
@@ -199,7 +198,7 @@
                 cmd.append('--repack')
             if revs:
                 cmd += ['-r', revs]
-            extutil.runbgcommand(cmd, encoding.environ)
+            procutil.runbgcommand(cmd, encoding.environ)
 
         def prefetch(self, revs, base=None, pats=None, opts=None):
             """Prefetches all the necessary file revisions for the given revs
--- a/mercurial/utils/procutil.py	Wed Oct 03 13:54:45 2018 -0400
+++ b/mercurial/utils/procutil.py	Wed Oct 03 14:01:04 2018 -0400
@@ -10,6 +10,7 @@
 from __future__ import absolute_import
 
 import contextlib
+import errno
 import imp
 import io
 import os
@@ -467,3 +468,74 @@
             signal.signal(signal.SIGINT, oldsiginthandler[0])
         if shouldbail:
             raise KeyboardInterrupt
+
+if pycompat.iswindows:
+    # no fork on Windows, but we can create a detached process
+    # https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863.aspx
+    # No stdlib constant exists for this value
+    DETACHED_PROCESS = 0x00000008
+    _creationflags = DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP
+
+    def runbgcommand(script, env, shell=False, stdout=None, stderr=None):
+        '''Spawn a command without waiting for it to finish.'''
+        # 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=shell, env=env, close_fds=True,
+            creationflags=_creationflags, stdout=stdout, stderr=stderr)
+else:
+    def runbgcommand(cmd, env, shell=False, stdout=None, stderr=None):
+        '''Spawn a command without waiting for it to finish.'''
+        # double-fork to completely detach from the parent process
+        # based on http://code.activestate.com/recipes/278731
+        pid = os.fork()
+        if pid:
+            # Parent process
+            (_pid, status) = os.waitpid(pid, 0)
+            if os.WIFEXITED(status):
+                returncode = os.WEXITSTATUS(status)
+            else:
+                returncode = -os.WTERMSIG(status)
+            if returncode != 0:
+                # The child process's return code is 0 on success, an errno
+                # value on failure, or 255 if we don't have a valid errno
+                # value.
+                #
+                # (It would be slightly nicer to return the full exception info
+                # over a pipe as the subprocess module does.  For now it
+                # doesn't seem worth adding that complexity here, though.)
+                if returncode == 255:
+                    returncode = errno.EINVAL
+                raise OSError(returncode, 'error running %r: %s' %
+                              (cmd, os.strerror(returncode)))
+            return
+
+        returncode = 255
+        try:
+            # Start a new session
+            os.setsid()
+
+            stdin = open(os.devnull, 'r')
+            if stdout is None:
+                stdout = open(os.devnull, 'w')
+            if stderr is None:
+                stderr = open(os.devnull, 'w')
+
+            # connect stdin to devnull to make sure the subprocess can't
+            # muck up that stream for mercurial.
+            subprocess.Popen(
+                cmd, shell=shell, env=env, close_fds=True,
+                stdin=stdin, stdout=stdout, stderr=stderr)
+            returncode = 0
+        except EnvironmentError as ex:
+            returncode = (ex.errno & 0xff)
+            if returncode == 0:
+                # This shouldn't happen, but just in case make sure the
+                # return code is never 0 here.
+                returncode = 255
+        except Exception:
+            returncode = 255
+        finally:
+            # mission accomplished, this child needs to exit and not
+            # continue the hg process here.
+            os._exit(returncode)