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