Mercurial > public > mercurial-scm > hg-stable
annotate mercurial/sshpeer.py @ 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 | dabf86721200 |
children | 3cd245945ef3 |
rev | line source |
---|---|
17192
1ac628cd7113
peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
16688
diff
changeset
|
1 # sshpeer.py - ssh repository proxy class for mercurial |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
2 # |
2859 | 3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com> |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
4 # |
8225
46293a0c7e9f
updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents:
8210
diff
changeset
|
5 # This software may be used and distributed according to the terms of the |
10263 | 6 # GNU General Public License version 2 or any later version. |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
7 |
25975
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
8 from __future__ import absolute_import |
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
9 |
15622
86fc364ca5f8
sshrepo: don't quote obviously safe strings (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents:
15581
diff
changeset
|
10 import re |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
11 import uuid |
25975
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
12 |
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
13 from .i18n import _ |
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
14 from . import ( |
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
15 error, |
33112
05906b8e1d23
py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents:
32062
diff
changeset
|
16 pycompat, |
25975
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
17 util, |
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
18 wireproto, |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
19 wireprotoserver, |
25975
de7a3893ee65
sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents:
25458
diff
changeset
|
20 ) |
60 | 21 |
15581
d8fa35c28335
ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents:
15017
diff
changeset
|
22 def _serverquote(s): |
35463
b520c8f98e1e
sshpeer: move docstring to top
Yuya Nishihara <yuya@tcha.org>
parents:
35440
diff
changeset
|
23 """quote a string for the remote shell ... which we assume is sh""" |
23671
e3f30068d2eb
sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents:
22935
diff
changeset
|
24 if not s: |
e3f30068d2eb
sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents:
22935
diff
changeset
|
25 return s |
15624
be43234a6d60
sshrepo: add more safe characters (issue2983)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
15622
diff
changeset
|
26 if re.match('[a-zA-Z0-9@%_+=:,./-]*$', s): |
15622
86fc364ca5f8
sshrepo: don't quote obviously safe strings (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents:
15581
diff
changeset
|
27 return s |
15581
d8fa35c28335
ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents:
15017
diff
changeset
|
28 return "'%s'" % s.replace("'", "'\\''") |
d8fa35c28335
ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents:
15017
diff
changeset
|
29 |
25244
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
30 def _forwardoutput(ui, pipe): |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
31 """display all data currently available on pipe as remote output. |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
32 |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
33 This is non blocking.""" |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
34 s = util.readpipe(pipe) |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
35 if s: |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
36 for l in s.splitlines(): |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
37 ui.status(_("remote: "), l, '\n') |
cf90764f40a4
sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25243
diff
changeset
|
38 |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
39 class doublepipe(object): |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
40 """Operate a side-channel pipe in addition of a main one |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
41 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
42 The side-channel pipe contains server output to be forwarded to the user |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
43 input. The double pipe will behave as the "main" pipe, but will ensure the |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
44 content of the "side" pipe is properly processed while we wait for blocking |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
45 call on the "main" pipe. |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
46 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
47 If large amounts of data are read from "main", the forward will cease after |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
48 the first bytes start to appear. This simplifies the implementation |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
49 without affecting actual output of sshpeer too much as we rarely issue |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
50 large read for data not yet emitted by the server. |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
51 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
52 The main pipe is expected to be a 'bufferedinputpipe' from the util module |
31953
cc2382b60007
sshpeer: fix docstring typo
Augie Fackler <augie@google.com>
parents:
31207
diff
changeset
|
53 that handle all the os specific bits. This class lives in this module |
26781
1aee2ab0f902
spelling: trivial spell checking
Mads Kiilerich <madski@unity3d.com>
parents:
26587
diff
changeset
|
54 because it focus on behavior specific to the ssh protocol.""" |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
55 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
56 def __init__(self, ui, main, side): |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
57 self._ui = ui |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
58 self._main = main |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
59 self._side = side |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
60 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
61 def _wait(self): |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
62 """wait until some data are available on main or side |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
63 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
64 return a pair of boolean (ismainready, issideready) |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
65 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
66 (This will only wait for data if the setup is supported by `util.poll`) |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
67 """ |
36400
066e6a9d52bb
sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36398
diff
changeset
|
68 if (isinstance(self._main, util.bufferedinputpipe) and |
066e6a9d52bb
sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36398
diff
changeset
|
69 self._main.hasbuffer): |
066e6a9d52bb
sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36398
diff
changeset
|
70 # Main has data. Assume side is worth poking at. |
066e6a9d52bb
sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36398
diff
changeset
|
71 return True, True |
066e6a9d52bb
sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36398
diff
changeset
|
72 |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
73 fds = [self._main.fileno(), self._side.fileno()] |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
74 try: |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
75 act = util.poll(fds) |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
76 except NotImplementedError: |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
77 # non supported yet case, assume all have data. |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
78 act = fds |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
79 return (self._main.fileno() in act, self._side.fileno() in act) |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
80 |
25456
408b7979bf03
sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25455
diff
changeset
|
81 def write(self, data): |
408b7979bf03
sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25455
diff
changeset
|
82 return self._call('write', data) |
408b7979bf03
sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25455
diff
changeset
|
83 |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
84 def read(self, size): |
32062
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
85 r = self._call('read', size) |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
86 if size != 0 and not r: |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
87 # We've observed a condition that indicates the |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
88 # stdout closed unexpectedly. Check stderr one |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
89 # more time and snag anything that's there before |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
90 # letting anyone know the main part of the pipe |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
91 # closed prematurely. |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
92 _forwardoutput(self._ui, self._side) |
ad6c5497cd15
sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents:
31953
diff
changeset
|
93 return r |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
94 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
95 def readline(self): |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
96 return self._call('readline') |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
97 |
25455
dc02a284e034
sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25422
diff
changeset
|
98 def _call(self, methname, data=None): |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
99 """call <methname> on "main", forward output of "side" while blocking |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
100 """ |
25455
dc02a284e034
sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25422
diff
changeset
|
101 # data can be '' or 0 |
dc02a284e034
sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25422
diff
changeset
|
102 if (data is not None and not data) or self._main.closed: |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
103 _forwardoutput(self._ui, self._side) |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
104 return '' |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
105 while True: |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
106 mainready, sideready = self._wait() |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
107 if sideready: |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
108 _forwardoutput(self._ui, self._side) |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
109 if mainready: |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
110 meth = getattr(self._main, methname) |
25455
dc02a284e034
sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25422
diff
changeset
|
111 if data is None: |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
112 return meth() |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
113 else: |
25455
dc02a284e034
sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25422
diff
changeset
|
114 return meth(data) |
25421
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
115 |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
116 def close(self): |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
117 return self._main.close() |
3dd3ccf7b807
sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25408
diff
changeset
|
118 |
25456
408b7979bf03
sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25455
diff
changeset
|
119 def flush(self): |
408b7979bf03
sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25455
diff
changeset
|
120 return self._main.flush() |
408b7979bf03
sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
25455
diff
changeset
|
121 |
35973
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
122 def _cleanuppipes(ui, pipei, pipeo, pipee): |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
123 """Clean up pipes used by an SSH connection.""" |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
124 if pipeo: |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
125 pipeo.close() |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
126 if pipei: |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
127 pipei.close() |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
128 |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
129 if pipee: |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
130 # Try to read from the err descriptor until EOF. |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
131 try: |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
132 for l in pipee: |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
133 ui.status(_('remote: '), l) |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
134 except (IOError, ValueError): |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
135 pass |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
136 |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
137 pipee.close() |
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
138 |
35975
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
139 def _makeconnection(ui, sshcmd, args, remotecmd, path, sshenv=None): |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
140 """Create an SSH connection to a server. |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
141 |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
142 Returns a tuple of (process, stdin, stdout, stderr) for the |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
143 spawned process. |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
144 """ |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
145 cmd = '%s %s %s' % ( |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
146 sshcmd, |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
147 args, |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
148 util.shellquote('%s -R %s serve --stdio' % ( |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
149 _serverquote(remotecmd), _serverquote(path)))) |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
150 |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
151 ui.debug('running %s\n' % cmd) |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
152 cmd = util.quotecommand(cmd) |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
153 |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
154 # no buffer allow the use of 'select' |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
155 # feel free to remove buffering and select usage when we ultimately |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
156 # move to threading. |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
157 stdin, stdout, stderr, proc = util.popen4(cmd, bufsize=0, env=sshenv) |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
158 |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
159 return proc, stdin, stdout, stderr |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
160 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
161 def _performhandshake(ui, stdin, stdout, stderr): |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
162 def badresponse(): |
36401
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
163 # Flush any output on stderr. |
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
164 _forwardoutput(ui, stderr) |
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
165 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
166 msg = _('no suitable response from remote hg') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
167 hint = ui.config('ui', 'ssherrorhint') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
168 raise error.RepoError(msg, hint=hint) |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
169 |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
170 # The handshake consists of sending wire protocol commands in reverse |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
171 # order of protocol implementation and then sniffing for a response |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
172 # to one of them. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
173 # |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
174 # Those commands (from oldest to newest) are: |
35979
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
175 # |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
176 # ``between`` |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
177 # Asks for the set of revisions between a pair of revisions. Command |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
178 # present in all Mercurial server implementations. |
35979
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
179 # |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
180 # ``hello`` |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
181 # Instructs the server to advertise its capabilities. Introduced in |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
182 # Mercurial 0.9.1. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
183 # |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
184 # ``upgrade`` |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
185 # Requests upgrade from default transport protocol version 1 to |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
186 # a newer version. Introduced in Mercurial 4.6 as an experimental |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
187 # feature. |
35979
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
188 # |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
189 # The ``between`` command is issued with a request for the null |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
190 # range. If the remote is a Mercurial server, this request will |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
191 # generate a specific response: ``1\n\n``. This represents the |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
192 # wire protocol encoded value for ``\n``. We look for ``1\n\n`` |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
193 # in the output stream and know this is the response to ``between`` |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
194 # and we're at the end of our handshake reply. |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
195 # |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
196 # The response to the ``hello`` command will be a line with the |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
197 # length of the value returned by that command followed by that |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
198 # value. If the server doesn't support ``hello`` (which should be |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
199 # rare), that line will be ``0\n``. Otherwise, the value will contain |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
200 # RFC 822 like lines. Of these, the ``capabilities:`` line contains |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
201 # the capabilities of the server. |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
202 # |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
203 # The ``upgrade`` command isn't really a command in the traditional |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
204 # sense of version 1 of the transport because it isn't using the |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
205 # proper mechanism for formatting insteads: instead, it just encodes |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
206 # arguments on the line, delimited by spaces. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
207 # |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
208 # The ``upgrade`` line looks like ``upgrade <token> <capabilities>``. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
209 # If the server doesn't support protocol upgrades, it will reply to |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
210 # this line with ``0\n``. Otherwise, it emits an |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
211 # ``upgraded <token> <protocol>`` line to both stdout and stderr. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
212 # Content immediately following this line describes additional |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
213 # protocol and server state. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
214 # |
35979
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
215 # In addition to the responses to our command requests, the server |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
216 # may emit "banner" output on stdout. SSH servers are allowed to |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
217 # print messages to stdout on login. Issuing commands on connection |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
218 # allows us to flush this banner output from the server by scanning |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
219 # for output to our well-known ``between`` command. Of course, if |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
220 # the banner contains ``1\n\n``, this will throw off our detection. |
a622a927fe03
sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35978
diff
changeset
|
221 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
222 requestlog = ui.configbool('devel', 'debug.peer-request') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
223 |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
224 # Generate a random token to help identify responses to version 2 |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
225 # upgrade request. |
36081
223ed0b53f08
py3: more robustly cast UUID to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36017
diff
changeset
|
226 token = pycompat.sysbytes(str(uuid.uuid4())) |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
227 upgradecaps = [ |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
228 ('proto', wireprotoserver.SSHV2), |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
229 ] |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
230 upgradecaps = util.urlreq.urlencode(upgradecaps) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
231 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
232 try: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
233 pairsarg = '%s-%s' % ('0' * 40, '0' * 40) |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
234 handshake = [ |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
235 'hello\n', |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
236 'between\n', |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
237 'pairs %d\n' % len(pairsarg), |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
238 pairsarg, |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
239 ] |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
240 |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
241 # Request upgrade to version 2 if configured. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
242 if ui.configbool('experimental', 'sshpeer.advertise-v2'): |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
243 ui.debug('sending upgrade request: %s %s\n' % (token, upgradecaps)) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
244 handshake.insert(0, 'upgrade %s %s\n' % (token, upgradecaps)) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
245 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
246 if requestlog: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
247 ui.debug('devel-peer-request: hello\n') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
248 ui.debug('sending hello command\n') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
249 if requestlog: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
250 ui.debug('devel-peer-request: between\n') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
251 ui.debug('devel-peer-request: pairs: %d bytes\n' % len(pairsarg)) |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
252 ui.debug('sending between command\n') |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
253 |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
254 stdin.write(''.join(handshake)) |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
255 stdin.flush() |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
256 except IOError: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
257 badresponse() |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
258 |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
259 # Assume version 1 of wire protocol by default. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
260 protoname = wireprotoserver.SSHV1 |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
261 reupgraded = re.compile(b'^upgraded %s (.*)$' % re.escape(token)) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
262 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
263 lines = ['', 'dummy'] |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
264 max_noise = 500 |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
265 while lines[-1] and max_noise: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
266 try: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
267 l = stdout.readline() |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
268 _forwardoutput(ui, stderr) |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
269 |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
270 # Look for reply to protocol upgrade request. It has a token |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
271 # in it, so there should be no false positives. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
272 m = reupgraded.match(l) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
273 if m: |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
274 protoname = m.group(1) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
275 ui.debug('protocol upgraded to %s\n' % protoname) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
276 # If an upgrade was handled, the ``hello`` and ``between`` |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
277 # requests are ignored. The next output belongs to the |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
278 # protocol, so stop scanning lines. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
279 break |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
280 |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
281 # Otherwise it could be a banner, ``0\n`` response if server |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
282 # doesn't support upgrade. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
283 |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
284 if lines[-1] == '1\n' and l == '\n': |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
285 break |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
286 if l: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
287 ui.debug('remote: ', l) |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
288 lines.append(l) |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
289 max_noise -= 1 |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
290 except IOError: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
291 badresponse() |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
292 else: |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
293 badresponse() |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
294 |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
295 caps = set() |
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
296 |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
297 # For version 1, we should see a ``capabilities`` line in response to the |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
298 # ``hello`` command. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
299 if protoname == wireprotoserver.SSHV1: |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
300 for l in reversed(lines): |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
301 # Look for response to ``hello`` command. Scan from the back so |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
302 # we don't misinterpret banner output as the command reply. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
303 if l.startswith('capabilities:'): |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
304 caps.update(l[:-1].split(':')[1].split()) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
305 break |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
306 elif protoname == wireprotoserver.SSHV2: |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
307 # We see a line with number of bytes to follow and then a value |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
308 # looking like ``capabilities: *``. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
309 line = stdout.readline() |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
310 try: |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
311 valuelen = int(line) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
312 except ValueError: |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
313 badresponse() |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
314 |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
315 capsline = stdout.read(valuelen) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
316 if not capsline.startswith('capabilities: '): |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
317 badresponse() |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
318 |
36254
7218e93ade47
sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36081
diff
changeset
|
319 ui.debug('remote: %s\n' % capsline) |
7218e93ade47
sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36081
diff
changeset
|
320 |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
321 caps.update(capsline.split(':')[1].split()) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
322 # Trailing newline. |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
323 stdout.read(1) |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
324 |
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
325 # Error if we couldn't find capabilities, this means: |
35980
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
326 # |
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
327 # 1. Remote isn't a Mercurial server |
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
328 # 2. Remote is a <0.9.1 Mercurial server |
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
329 # 3. Remote is a future Mercurial server that dropped ``hello`` |
36015
48a3a9283f09
sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35980
diff
changeset
|
330 # and other attempted handshake mechanisms. |
35980
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
331 if not caps: |
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
332 badresponse() |
556218e08e25
sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35979
diff
changeset
|
333 |
36401
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
334 # Flush any output on stderr before proceeding. |
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
335 _forwardoutput(ui, stderr) |
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
336 |
36017
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
337 return protoname, caps |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
338 |
36016
625038cb4b1d
sshpeer: rename sshpeer class to sshv1peer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36015
diff
changeset
|
339 class sshv1peer(wireproto.wirepeer): |
36562
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
340 def __init__(self, ui, url, proc, stdin, stdout, stderr, caps, |
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
341 autoreadstderr=True): |
35976
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
342 """Create a peer from an existing SSH connection. |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
343 |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
344 ``proc`` is a handle on the underlying SSH process. |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
345 ``stdin``, ``stdout``, and ``stderr`` are handles on the stdio |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
346 pipes for that process. |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
347 ``caps`` is a set of capabilities supported by the remote. |
36562
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
348 ``autoreadstderr`` denotes whether to automatically read from |
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
349 stderr and to forward its output. |
35976
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
350 """ |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
351 self._url = url |
33825
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
352 self._ui = ui |
35975
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
353 # self._subprocess is unused. Keeping a handle on the process |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
354 # holds a reference and prevents it from being garbage collected. |
35976
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
355 self._subprocess = proc |
36401
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
356 |
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
357 # And we hook up our "doublepipe" wrapper to allow querying |
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
358 # stderr any time we perform I/O. |
36562
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
359 if autoreadstderr: |
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
360 stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr) |
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
361 stdin = doublepipe(ui, stdin, stderr) |
36401
11ba1a96f946
sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36400
diff
changeset
|
362 |
35976
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
363 self._pipeo = stdin |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
364 self._pipei = stdout |
f8f034344b39
sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35975
diff
changeset
|
365 self._pipee = stderr |
35978
80a2b8ae42a1
sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35977
diff
changeset
|
366 self._caps = caps |
2549
e1831f06eef1
Added ability to clone from a local repository to a (new) remote one.
Sean Meiners <sean.meiners@linspire.com>
parents:
2484
diff
changeset
|
367 |
36398
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
368 # Commands that have a "framed" response where the first line of the |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
369 # response contains the length of that response. |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
370 _FRAMED_COMMANDS = { |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
371 'batch', |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
372 } |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
373 |
33825
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
374 # Begin of _basepeer interface. |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
375 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
376 @util.propertycache |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
377 def ui(self): |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
378 return self._ui |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
379 |
2673
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
380 def url(self): |
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
381 return self._url |
109a22f5434a
hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2612
diff
changeset
|
382 |
33825
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
383 def local(self): |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
384 return None |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
385 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
386 def peer(self): |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
387 return self |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
388 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
389 def canpush(self): |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
390 return True |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
391 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
392 def close(self): |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
393 pass |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
394 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
395 # End of _basepeer interface. |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
396 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
397 # Begin of _basewirecommands interface. |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
398 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
399 def capabilities(self): |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
400 return self._caps |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
401 |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
402 # End of _basewirecommands interface. |
1f8460b55986
sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33789
diff
changeset
|
403 |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
404 def _readerr(self): |
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
405 _forwardoutput(self.ui, self._pipee) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
406 |
11586
ddaaaa23bb8f
protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents:
11369
diff
changeset
|
407 def _abort(self, exception): |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
408 self._cleanup() |
11586
ddaaaa23bb8f
protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents:
11369
diff
changeset
|
409 raise exception |
ddaaaa23bb8f
protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents:
11369
diff
changeset
|
410 |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
411 def _cleanup(self): |
35973
805edf16e8e0
sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35972
diff
changeset
|
412 _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee) |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
413 |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
414 __del__ = _cleanup |
3034
2b0bc36a48d8
sshrepo: flush stderr before connecting to the hg server
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
2859
diff
changeset
|
415 |
36398
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
416 def _sendrequest(self, cmd, args, framed=False): |
35699
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
417 if (self.ui.debugflag |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
418 and self.ui.configbool('devel', 'debug.peer-request')): |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
419 dbg = self.ui.debug |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
420 line = 'devel-peer-request: %s\n' |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
421 dbg(line % cmd) |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
422 for key, value in sorted(args.items()): |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
423 if not isinstance(value, dict): |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
424 dbg(line % ' %s: %d bytes' % (key, len(value))) |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
425 else: |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
426 for dk, dv in sorted(value.items()): |
f7ef49e44d7c
sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents:
35463
diff
changeset
|
427 dbg(line % ' %s-%s: %d' % (key, dk, len(dv))) |
9467
4c041f1ee1b4
do not attempt to translate ui.debug output
Martin Geisler <mg@lazybytes.net>
parents:
8563
diff
changeset
|
428 self.ui.debug("sending %s command\n" % cmd) |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
429 self._pipeo.write("%s\n" % cmd) |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
430 _func, names = wireproto.commands[cmd] |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
431 keys = names.split() |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
432 wireargs = {} |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
433 for k in keys: |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
434 if k == '*': |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
435 wireargs['*'] = args |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
436 break |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
437 else: |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
438 wireargs[k] = args[k] |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
439 del args[k] |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
440 for k, v in sorted(wireargs.iteritems()): |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
441 self._pipeo.write("%s %d\n" % (k, len(v))) |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
442 if isinstance(v, dict): |
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
443 for dk, dv in v.iteritems(): |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
444 self._pipeo.write("%s %d\n" % (dk, len(dv))) |
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
445 self._pipeo.write(dv) |
13721
3458c15ab2f0
wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents:
13464
diff
changeset
|
446 else: |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
447 self._pipeo.write(v) |
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
448 self._pipeo.flush() |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
449 |
36398
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
450 # We know exactly how many bytes are in the response. So return a proxy |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
451 # around the raw output stream that allows reading exactly this many |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
452 # bytes. Callers then can read() without fear of overrunning the |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
453 # response. |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
454 if framed: |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
455 amount = self._getamount() |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
456 return util.cappedreader(self._pipei, amount) |
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
457 |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
458 return self._pipei |
624
876333a295ff
Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents:
623
diff
changeset
|
459 |
36397
a34d5ef53c2e
sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36396
diff
changeset
|
460 def _callstream(self, cmd, **args): |
a34d5ef53c2e
sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36396
diff
changeset
|
461 args = pycompat.byteskwargs(args) |
36398
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
462 return self._sendrequest(cmd, args, framed=cmd in self._FRAMED_COMMANDS) |
36397
a34d5ef53c2e
sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36396
diff
changeset
|
463 |
20905
167047ba3cfa
wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20794
diff
changeset
|
464 def _callcompressable(self, cmd, **args): |
36397
a34d5ef53c2e
sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36396
diff
changeset
|
465 args = pycompat.byteskwargs(args) |
36398
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
466 return self._sendrequest(cmd, args, framed=cmd in self._FRAMED_COMMANDS) |
20905
167047ba3cfa
wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20794
diff
changeset
|
467 |
11589
e8d22fe2ddab
protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents:
11588
diff
changeset
|
468 def _call(self, cmd, **args): |
36397
a34d5ef53c2e
sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36396
diff
changeset
|
469 args = pycompat.byteskwargs(args) |
36398
043e77f3be09
sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36397
diff
changeset
|
470 return self._sendrequest(cmd, args, framed=True).read() |
5978
7939c71f3132
sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5293
diff
changeset
|
471 |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
472 def _callpush(self, cmd, fp, **args): |
36403
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
473 # The server responds with an empty frame if the client should |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
474 # continue submitting the payload. |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
475 r = self._call(cmd, **args) |
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
476 if r: |
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
477 return '', r |
36403
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
478 |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
479 # The payload consists of frames with content followed by an empty |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
480 # frame. |
29739
0dbd788a2dfd
sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents:
29389
diff
changeset
|
481 for d in iter(lambda: fp.read(4096), ''): |
36396
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
482 self._writeframed(d) |
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
483 self._writeframed("", flush=True) |
36403
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
484 |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
485 # In case of success, there is an empty frame and a frame containing |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
486 # the integer result (as a string). |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
487 # In case of error, there is a non-empty frame containing the error. |
36396
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
488 r = self._readframed() |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
489 if r: |
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
490 return '', r |
36396
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
491 return self._readframed(), '' |
11592
26e0782b8380
protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents:
11591
diff
changeset
|
492 |
21073
83ce71ef7804
sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
493 def _calltwowaystream(self, cmd, fp, **args): |
36403
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
494 # The server responds with an empty frame if the client should |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
495 # continue submitting the payload. |
21073
83ce71ef7804
sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
496 r = self._call(cmd, **args) |
83ce71ef7804
sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
497 if r: |
83ce71ef7804
sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
20905
diff
changeset
|
498 # XXX needs to be made better |
29389
98e8313dcd9e
i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents:
28438
diff
changeset
|
499 raise error.Abort(_('unexpected remote reply: %s') % r) |
36403
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
500 |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
501 # The payload consists of frames with content followed by an empty |
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
502 # frame. |
29739
0dbd788a2dfd
sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents:
29389
diff
changeset
|
503 for d in iter(lambda: fp.read(4096), ''): |
36396
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
504 self._writeframed(d) |
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
505 self._writeframed("", flush=True) |
36403
b8d0761a85c7
wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36401
diff
changeset
|
506 |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
507 return self._pipei |
11591
0d9cb3f3b0a1
protocol: unify client changegroup methods
Matt Mackall <mpm@selenic.com>
parents:
11590
diff
changeset
|
508 |
28438
48fd02dac1d4
wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents:
27798
diff
changeset
|
509 def _getamount(self): |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
510 l = self._pipei.readline() |
15017
f4522df38c65
wireproto: add out-of-band error class to allow remote repo to report errors
Andrew Pritchard <andrewp@fogcreek.com>
parents:
14537
diff
changeset
|
511 if l == '\n': |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
512 self._readerr() |
25243
d65243d28749
sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23684
diff
changeset
|
513 msg = _('check previous remote output') |
d65243d28749
sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents:
23684
diff
changeset
|
514 self._abort(error.OutOfBandError(hint=msg)) |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
515 self._readerr() |
646
342927da4f4c
Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents:
644
diff
changeset
|
516 try: |
28438
48fd02dac1d4
wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents:
27798
diff
changeset
|
517 return int(l) |
14004
97ed99d1f419
eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents:
13827
diff
changeset
|
518 except ValueError: |
11590
0b15aee0a306
protocol: convert some ssh abort calls
Matt Mackall <mpm@selenic.com>
parents:
11589
diff
changeset
|
519 self._abort(error.ResponseError(_("unexpected response:"), l)) |
28438
48fd02dac1d4
wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents:
27798
diff
changeset
|
520 |
36396
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
521 def _readframed(self): |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
522 return self._pipei.read(self._getamount()) |
5978
7939c71f3132
sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5293
diff
changeset
|
523 |
36396
7f8f74531b0b
sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36254
diff
changeset
|
524 def _writeframed(self, data, flush=False): |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
525 self._pipeo.write("%d\n" % len(data)) |
5978
7939c71f3132
sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5293
diff
changeset
|
526 if data: |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
527 self._pipeo.write(data) |
5978
7939c71f3132
sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents:
5293
diff
changeset
|
528 if flush: |
33789
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
529 self._pipeo.flush() |
82d564d5ac4f
sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents:
33763
diff
changeset
|
530 self._readerr() |
2612
ffb895f16925
add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
2549
diff
changeset
|
531 |
36017
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
532 class sshv2peer(sshv1peer): |
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
533 """A peer that speakers version 2 of the transport protocol.""" |
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
534 # Currently version 2 is identical to version 1 post handshake. |
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
535 # And handshake is performed before the peer is instantiated. So |
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
536 # we need no custom code. |
59e4a7781a36
sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36016
diff
changeset
|
537 |
36562
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
538 def makepeer(ui, path, proc, stdin, stdout, stderr, autoreadstderr=True): |
36517
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
539 """Make a peer instance from existing pipes. |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
540 |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
541 ``path`` and ``proc`` are stored on the eventual peer instance and may |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
542 not be used for anything meaningful. |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
543 |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
544 ``stdin``, ``stdout``, and ``stderr`` are the pipes connected to the |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
545 SSH server's stdio handles. |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
546 |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
547 This function is factored out to allow creating peers that don't |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
548 actually spawn a new process. It is useful for starting SSH protocol |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
549 servers and clients via non-standard means, which can be useful for |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
550 testing. |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
551 """ |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
552 try: |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
553 protoname, caps = _performhandshake(ui, stdin, stdout, stderr) |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
554 except Exception: |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
555 _cleanuppipes(ui, stdout, stdin, stderr) |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
556 raise |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
557 |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
558 if protoname == wireprotoserver.SSHV1: |
36562
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
559 return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps, |
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
560 autoreadstderr=autoreadstderr) |
36517
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
561 elif protoname == wireprotoserver.SSHV2: |
36562
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
562 return sshv2peer(ui, path, proc, stdin, stdout, stderr, caps, |
1a36ef7df70a
sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36517
diff
changeset
|
563 autoreadstderr=autoreadstderr) |
36517
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
564 else: |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
565 _cleanuppipes(ui, stdout, stdin, stderr) |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
566 raise error.RepoError(_('unknown version of SSH protocol: %s') % |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
567 protoname) |
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
568 |
35968
b0d2885c5945
sshpeer: make "instance" a function
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35699
diff
changeset
|
569 def instance(ui, path, create): |
35971
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
570 """Create an SSH peer. |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
571 |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
572 The returned object conforms to the ``wireproto.wirepeer`` interface. |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
573 """ |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
574 u = util.url(path, parsequery=False, parsefragment=False) |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
575 if u.scheme != 'ssh' or not u.host or u.path is None: |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
576 raise error.RepoError(_("couldn't parse location %s") % path) |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
577 |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
578 util.checksafessh(path) |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
579 |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
580 if u.passwd is not None: |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
581 raise error.RepoError(_('password in URL not supported')) |
b202d360d2a4
sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35968
diff
changeset
|
582 |
35972
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
583 sshcmd = ui.config('ui', 'ssh') |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
584 remotecmd = ui.config('ui', 'remotecmd') |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
585 sshaddenv = dict(ui.configitems('sshenv')) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
586 sshenv = util.shellenviron(sshaddenv) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
587 remotepath = u.path or '.' |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
588 |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
589 args = util.sshargs(sshcmd, u.host, u.user, u.port) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
590 |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
591 if create: |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
592 cmd = '%s %s %s' % (sshcmd, args, |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
593 util.shellquote('%s init %s' % |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
594 (_serverquote(remotecmd), _serverquote(remotepath)))) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
595 ui.debug('running %s\n' % cmd) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
596 res = ui.system(cmd, blockedtag='sshpeer', environ=sshenv) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
597 if res != 0: |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
598 raise error.RepoError(_('could not create remote repo')) |
31449baf0936
sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35971
diff
changeset
|
599 |
35975
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
600 proc, stdin, stdout, stderr = _makeconnection(ui, sshcmd, args, remotecmd, |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
601 remotepath, sshenv) |
00b9e26d727b
sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents:
35974
diff
changeset
|
602 |
36517
dabf86721200
sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents:
36403
diff
changeset
|
603 return makepeer(ui, path, proc, stdin, stdout, stderr) |