##// END OF EJS Templates
sshpeer: introduce a "doublepipe" class...
Pierre-Yves David -
r25421:3dd3ccf7 default
parent child Browse files
Show More
@@ -36,6 +36,71 b' def _forwardoutput(ui, pipe):'
36 36 for l in s.splitlines():
37 37 ui.status(_("remote: "), l, '\n')
38 38
39 class doublepipe(object):
40 """Operate a side-channel pipe in addition of a main one
41
42 The side-channel pipe contains server output to be forwarded to the user
43 input. The double pipe will behave as the "main" pipe, but will ensure the
44 content of the "side" pipe is properly processed while we wait for blocking
45 call on the "main" pipe.
46
47 If large amounts of data are read from "main", the forward will cease after
48 the first bytes start to appear. This simplifies the implementation
49 without affecting actual output of sshpeer too much as we rarely issue
50 large read for data not yet emitted by the server.
51
52 The main pipe is expected to be a 'bufferedinputpipe' from the util module
53 that handle all the os specific bites. This class lives in this module
54 because it focus on behavior specifig to the ssh protocol."""
55
56 def __init__(self, ui, main, side):
57 self._ui = ui
58 self._main = main
59 self._side = side
60
61 def _wait(self):
62 """wait until some data are available on main or side
63
64 return a pair of boolean (ismainready, issideready)
65
66 (This will only wait for data if the setup is supported by `util.poll`)
67 """
68 if self._main.hasbuffer:
69 return (True, True) # main has data, assume side is worth poking at.
70 fds = [self._main.fileno(), self._side.fileno()]
71 try:
72 act = util.poll(fds)
73 except NotImplementedError:
74 # non supported yet case, assume all have data.
75 act = fds
76 return (self._main.fileno() in act, self._side.fileno() in act)
77
78 def read(self, size):
79 return self._call('read', size)
80
81 def readline(self):
82 return self._call('readline')
83
84 def _call(self, methname, size=None):
85 """call <methname> on "main", forward output of "side" while blocking
86 """
87 if size == 0 or self._main.closed:
88 _forwardoutput(self._ui, self._side)
89 return ''
90 while True:
91 mainready, sideready = self._wait()
92 if sideready:
93 _forwardoutput(self._ui, self._side)
94 if mainready:
95 meth = getattr(self._main, methname)
96 if size is None:
97 return meth()
98 else:
99 return meth(size)
100
101 def close(self):
102 return self._main.close()
103
39 104 class sshpeer(wireproto.wirepeer):
40 105 def __init__(self, ui, path, create=False):
41 106 self._url = path
General Comments 0
You need to be logged in to leave comments. Login now