changeset 36562:1a36ef7df70a

sshpeer: support not reading and forwarding stderr The "doublepipe" primitive as used by sshpeer will automatically read from stderr and forward output to the local ui. This poses problems for deterministic testing because reads may not be consistent. For example, the server may not be done sending all output to stderr and the client will perform different numbers of read operations or will read from stderr and stdout at different times. To make tests deterministic, we'll need to disable the "doublepipe" primitive and perform stderr I/O explicitly. We add an argument to the sshpeer constructor to disable the use of the doublepipe. Differential Revision: https://phab.mercurial-scm.org/D2467
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 26 Feb 2018 13:12:03 -0800
parents 1138e5c0fbc9
children 5faeabb07cf5
files mercurial/sshpeer.py
diffstat 1 files changed, 12 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/sshpeer.py	Fri Feb 23 16:03:27 2018 -0800
+++ b/mercurial/sshpeer.py	Mon Feb 26 13:12:03 2018 -0800
@@ -337,13 +337,16 @@
     return protoname, caps
 
 class sshv1peer(wireproto.wirepeer):
-    def __init__(self, ui, url, proc, stdin, stdout, stderr, caps):
+    def __init__(self, ui, url, proc, stdin, stdout, stderr, caps,
+                 autoreadstderr=True):
         """Create a peer from an existing SSH connection.
 
         ``proc`` is a handle on the underlying SSH process.
         ``stdin``, ``stdout``, and ``stderr`` are handles on the stdio
         pipes for that process.
         ``caps`` is a set of capabilities supported by the remote.
+        ``autoreadstderr`` denotes whether to automatically read from
+        stderr and to forward its output.
         """
         self._url = url
         self._ui = ui
@@ -353,8 +356,9 @@
 
         # And we hook up our "doublepipe" wrapper to allow querying
         # stderr any time we perform I/O.
-        stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr)
-        stdin = doublepipe(ui, stdin, stderr)
+        if autoreadstderr:
+            stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr)
+            stdin = doublepipe(ui, stdin, stderr)
 
         self._pipeo = stdin
         self._pipei = stdout
@@ -531,7 +535,7 @@
     # And handshake is performed before the peer is instantiated. So
     # we need no custom code.
 
-def makepeer(ui, path, proc, stdin, stdout, stderr):
+def makepeer(ui, path, proc, stdin, stdout, stderr, autoreadstderr=True):
     """Make a peer instance from existing pipes.
 
     ``path`` and ``proc`` are stored on the eventual peer instance and may
@@ -552,9 +556,11 @@
         raise
 
     if protoname == wireprotoserver.SSHV1:
-        return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps)
+        return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps,
+                         autoreadstderr=autoreadstderr)
     elif protoname == wireprotoserver.SSHV2:
-        return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps)
+        return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps,
+                         autoreadstderr=autoreadstderr)
     else:
         _cleanuppipes(ui, stdout, stdin, stderr)
         raise error.RepoError(_('unknown version of SSH protocol: %s') %