Show More
@@ -36,6 +36,71 b' def _forwardoutput(ui, pipe):' | |||||
36 | for l in s.splitlines(): |
|
36 | for l in s.splitlines(): | |
37 | ui.status(_("remote: "), l, '\n') |
|
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 | class sshpeer(wireproto.wirepeer): |
|
104 | class sshpeer(wireproto.wirepeer): | |
40 | def __init__(self, ui, path, create=False): |
|
105 | def __init__(self, ui, path, create=False): | |
41 | self._url = path |
|
106 | self._url = path |
General Comments 0
You need to be logged in to leave comments.
Login now