Patchwork D9212: procutil: allow to specify arbitrary stdin bytes to runbgcommand

login
register
mail settings
Submitter phabricator
Date Oct. 14, 2020, 11:34 p.m.
Message ID <differential-rev-PHID-DREV-2cm6yoepmmcplczhxi32-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47469/
State Superseded
Headers show

Comments

phabricator - Oct. 14, 2020, 11:34 p.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  For automatic clonebundles generation I need to pass arbitrary large amount of
  data to the process (eg: common nodes, target nodes).
  
  I am updating the `runbgcommand` to allow for this. Previously not stdin input
  was possible, now, one can provide raw bytes and they will be feed to the
  command through an unnamed temporary files.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9212

AFFECTED FILES
  mercurial/utils/procutil.py

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/mercurial/utils/procutil.py b/mercurial/utils/procutil.py
--- a/mercurial/utils/procutil.py
+++ b/mercurial/utils/procutil.py
@@ -635,21 +635,35 @@ 
         stderr=None,
         ensurestart=True,
         record_wait=None,
+        stdin_bytes=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.
-        p = subprocess.Popen(
-            tonativestr(script),
-            shell=shell,
-            env=tonativeenv(env),
-            close_fds=True,
-            creationflags=_creationflags,
-            stdout=stdout,
-            stderr=stderr,
-        )
-        if record_wait is not None:
-            record_wait(p.wait)
+
+        try:
+            stdin = None
+            if stdin_bytes is not None:
+                stdin = pycompat.unnamedtempfile()
+                stdin.write(stdin_bytes)
+                stdin.flush()
+                stdin.seek(0)
+
+            p = subprocess.Popen(
+                tonativestr(script),
+                shell=shell,
+                env=tonativeenv(env),
+                close_fds=True,
+                creationflags=_creationflags,
+                stdin=stdin,
+                stdout=stdout,
+                stderr=stderr,
+            )
+            if record_wait is not None:
+                record_wait(p.wait)
+        finally:
+            if stdin is not None:
+                stdin.close()
 
 
 else:
@@ -662,6 +676,7 @@ 
         stderr=None,
         ensurestart=True,
         record_wait=None,
+        stdin_bytes=None,
     ):
         '''Spawn a command without waiting for it to finish.
 
@@ -722,15 +737,21 @@ 
             if record_wait is None:
                 # Start a new session
                 os.setsid()
+            # connect stdin to devnull to make sure the subprocess can't
+            # muck up that stream for mercurial.
+            if stdin_bytes is None:
+                stdin = open(os.devnull, b'r')
+            else:
+                stdin = pycompat.unnamedtempfile()
+                stdin.write(stdin_bytes)
+                stdin.flush()
+                stdin.seek(0)
 
-            stdin = open(os.devnull, b'r')
             if stdout is None:
                 stdout = open(os.devnull, b'w')
             if stderr is None:
                 stderr = open(os.devnull, b'w')
 
-            # connect stdin to devnull to make sure the subprocess can't
-            # muck up that stream for mercurial.
             p = subprocess.Popen(
                 cmd,
                 shell=shell,
@@ -754,5 +775,6 @@ 
         finally:
             # mission accomplished, this child needs to exit and not
             # continue the hg process here.
+            stdin.close()
             if record_wait is None:
                 os._exit(returncode)