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
--- 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)