mercurial/sshpeer.py
author Gregory Szorc <gregory.szorc@gmail.com>
Tue, 06 Feb 2018 10:57:56 -0800
changeset 36016 625038cb4b1d
parent 36015 48a3a9283f09
child 36017 59e4a7781a36
permissions -rw-r--r--
sshpeer: rename sshpeer class to sshv1peer (API) With the introduction of version 2 of the SSH wire protocol, we will need a new peer class to speak that protocol because it will be too difficult to shoehorn a single class to speak two protocols. We rename sshpeer.sshpeer to sshpeer.sshv1peer to reflect the fact that there will be multiple versions of the peer depending on the negotiated protocol. .. api:: sshpeer.sshpeer renamed to sshpeer.sshv1peer. Differential Revision: https://phab.mercurial-scm.org/D2062
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
345bac2bc4ec update copyrights.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2740
diff changeset
     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
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9878
diff changeset
     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
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
    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
        """
25457
2afa748138e0 sshpeer: allow doublepipe on unbuffered main pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25456
diff changeset
    68
        if getattr(self._main, 'hasbuffer', False): # getattr for classic pipe
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    69
            return (True, True) # main has data, assume side is worth poking at.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    70
        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
    71
        try:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    72
            act = util.poll(fds)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    73
        except NotImplementedError:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    74
            # 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
    75
            act = fds
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    76
        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
    77
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
    78
    def write(self, data):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
    79
        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
    80
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    81
    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
    82
        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
    83
        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
    84
            # 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
    85
            # 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
    86
            # 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
    87
            # 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
    88
            # closed prematurely.
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
    89
            _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
    90
        return r
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    91
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    92
    def readline(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    93
        return self._call('readline')
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    94
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
    95
    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
    96
        """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
    97
        """
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
    98
        # 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
    99
        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
   100
            _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   101
            return ''
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   102
        while True:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   103
            mainready, sideready = self._wait()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   104
            if sideready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   105
                _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   106
            if mainready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   107
                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
   108
                if data is None:
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   109
                    return meth()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   110
                else:
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
   111
                    return meth(data)
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   112
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   113
    def close(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   114
        return self._main.close()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   115
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   116
    def flush(self):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   117
        return self._main.flush()
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   118
35973
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   119
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
   120
    """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
   121
    if pipeo:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   122
        pipeo.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   123
    if pipei:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   124
        pipei.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   125
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   126
    if pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   127
        # 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
   128
        try:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   129
            for l in pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   130
                ui.status(_('remote: '), l)
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   131
        except (IOError, ValueError):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   132
            pass
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   133
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   134
        pipee.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   135
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   136
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
   137
    """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
   138
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   139
    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
   140
    spawned process.
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
    cmd = '%s %s %s' % (
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   143
        sshcmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   144
        args,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   145
        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
   146
            _serverquote(remotecmd), _serverquote(path))))
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   147
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   148
    ui.debug('running %s\n' % cmd)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   149
    cmd = util.quotecommand(cmd)
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
    # 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
   152
    # 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
   153
    # move to threading.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   154
    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
   155
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   156
    stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   157
    stdin = doublepipe(ui, stdin, stderr)
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():
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   163
        msg = _('no suitable response from remote hg')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   164
        hint = ui.config('ui', 'ssherrorhint')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   165
        raise error.RepoError(msg, hint=hint)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   166
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   167
    # 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
   168
    # 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
   169
    # to one of them.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   170
    #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   171
    # Those commands (from oldest to newest) are:
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   172
    #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   173
    # ``between``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   174
    #   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
   175
    #   present in all Mercurial server implementations.
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   176
    #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   177
    # ``hello``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   178
    #   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
   179
    #   Mercurial 0.9.1.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   180
    #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   181
    # ``upgrade``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   182
    #   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
   183
    #   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
   184
    #   feature.
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   185
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   186
    # 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
   187
    # 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
   188
    # 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
   189
    # 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
   190
    # 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
   191
    # 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
   192
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   193
    # 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
   194
    # 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
   195
    # 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
   196
    # 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
   197
    # 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
   198
    # the capabilities of the server.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   199
    #
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   200
    # 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
   201
    # 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
   202
    # 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
   203
    # 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
   204
    #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   205
    # 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
   206
    # 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
   207
    # 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
   208
    # ``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
   209
    # 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
   210
    # protocol and server state.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   211
    #
35979
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   212
    # 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
   213
    # 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
   214
    # 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
   215
    # 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
   216
    # 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
   217
    # 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
   218
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   219
    requestlog = ui.configbool('devel', 'debug.peer-request')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   220
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   221
    # 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
   222
    # upgrade request.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   223
    token = bytes(uuid.uuid4())
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   224
    upgradecaps = [
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   225
        ('proto', wireprotoserver.SSHV2),
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   226
    ]
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   227
    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
   228
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   229
    try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   230
        pairsarg = '%s-%s' % ('0' * 40, '0' * 40)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   231
        handshake = [
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   232
            'hello\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   233
            'between\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   234
            'pairs %d\n' % len(pairsarg),
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   235
            pairsarg,
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   236
        ]
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   237
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   238
        # 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
   239
        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
   240
            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
   241
            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
   242
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   243
        if requestlog:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   244
            ui.debug('devel-peer-request: hello\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   245
        ui.debug('sending hello command\n')
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: between\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   248
            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
   249
        ui.debug('sending between command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   250
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   251
        stdin.write(''.join(handshake))
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   252
        stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   253
    except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   254
        badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   255
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   256
    # 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
   257
    protoname = wireprotoserver.SSHV1
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   258
    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
   259
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   260
    lines = ['', 'dummy']
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   261
    max_noise = 500
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   262
    while lines[-1] and max_noise:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   263
        try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   264
            l = stdout.readline()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   265
            _forwardoutput(ui, stderr)
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   266
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   267
            # 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
   268
            # 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
   269
            m = reupgraded.match(l)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   270
            if m:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   271
                protoname = m.group(1)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   272
                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
   273
                # 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
   274
                # 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
   275
                # 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
   276
                break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   277
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   278
            # 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
   279
            # doesn't support upgrade.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   280
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   281
            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
   282
                break
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   283
            if l:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   284
                ui.debug('remote: ', l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   285
            lines.append(l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   286
            max_noise -= 1
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   287
        except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   288
            badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   289
    else:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   290
        badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   291
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   292
    caps = set()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   293
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   294
    # 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
   295
    # ``hello`` command.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   296
    if protoname == wireprotoserver.SSHV1:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   297
        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
   298
            # 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
   299
            # 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
   300
            if l.startswith('capabilities:'):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   301
                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
   302
                break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   303
    elif protoname == wireprotoserver.SSHV2:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   304
        # 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
   305
        # looking like ``capabilities: *``.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   306
        line = stdout.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   307
        try:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   308
            valuelen = int(line)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   309
        except ValueError:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   310
            badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   311
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   312
        capsline = stdout.read(valuelen)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   313
        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
   314
            badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   315
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   316
        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
   317
        # Trailing newline.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   318
        stdout.read(1)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   319
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35980
diff changeset
   320
    # 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
   321
    #
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
   322
    # 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
   323
    # 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
   324
    # 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
   325
    #    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
   326
    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
   327
        badresponse()
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35979
diff changeset
   328
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   329
    return caps
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   330
36016
625038cb4b1d sshpeer: rename sshpeer class to sshv1peer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36015
diff changeset
   331
class sshv1peer(wireproto.wirepeer):
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   332
    def __init__(self, ui, url, proc, stdin, stdout, stderr, caps):
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   333
        """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
   334
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   335
        ``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
   336
        ``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
   337
        pipes for that process.
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   338
        ``caps`` is a set of capabilities supported by the remote.
35976
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   339
        """
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   340
        self._url = url
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   341
        self._ui = ui
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   342
        # 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
   343
        # 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
   344
        self._subprocess = proc
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   345
        self._pipeo = stdin
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   346
        self._pipei = stdout
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35975
diff changeset
   347
        self._pipee = stderr
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   348
        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
   349
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   350
    # Begin of _basepeer interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   351
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   352
    @util.propertycache
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   353
    def ui(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   354
        return self._ui
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   355
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   356
    def url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   357
        return self._url
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   358
33825
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   359
    def local(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   360
        return None
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   361
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   362
    def peer(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   363
        return self
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   364
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   365
    def canpush(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   366
        return True
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   367
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   368
    def close(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   369
        pass
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   370
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   371
    # End of _basepeer interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   372
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   373
    # Begin of _basewirecommands interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   374
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   375
    def capabilities(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   376
        return self._caps
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   377
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   378
    # End of _basewirecommands interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33789
diff changeset
   379
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   380
    def _readerr(self):
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   381
        _forwardoutput(self.ui, self._pipee)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   382
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   383
    def _abort(self, exception):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   384
        self._cleanup()
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   385
        raise exception
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   386
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   387
    def _cleanup(self):
35973
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35972
diff changeset
   388
        _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
   389
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   390
    __del__ = _cleanup
3034
2b0bc36a48d8 sshrepo: flush stderr before connecting to the hg server
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
   391
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   392
    def _submitbatch(self, req):
29745
bb04f96df51c wireproto: consolidate code for obtaining "cmds" argument value
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29739
diff changeset
   393
        rsp = self._callstream("batch", cmds=wireproto.encodebatchcmds(req))
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   394
        available = self._getamount()
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   395
        # TODO this response parsing is probably suboptimal for large
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   396
        # batches with large responses.
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   397
        toread = min(available, 1024)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   398
        work = rsp.read(toread)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   399
        available -= toread
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   400
        chunk = work
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   401
        while chunk:
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   402
            while ';' in work:
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   403
                one, work = work.split(';', 1)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   404
                yield wireproto.unescapearg(one)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   405
            toread = min(available, 1024)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   406
            chunk = rsp.read(toread)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   407
            available -= toread
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   408
            work += chunk
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   409
        yield wireproto.unescapearg(work)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   410
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   411
    def _callstream(self, cmd, **args):
33112
05906b8e1d23 py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32062
diff changeset
   412
        args = pycompat.byteskwargs(args)
35699
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   413
        if (self.ui.debugflag
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   414
            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
   415
            dbg = self.ui.debug
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   416
            line = 'devel-peer-request: %s\n'
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   417
            dbg(line % cmd)
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   418
            for key, value in sorted(args.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   419
                if not isinstance(value, dict):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   420
                    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
   421
                else:
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   422
                    for dk, dv in sorted(value.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35463
diff changeset
   423
                        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
   424
        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
   425
        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
   426
        _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
   427
        keys = names.split()
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   428
        wireargs = {}
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   429
        for k in keys:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   430
            if k == '*':
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   431
                wireargs['*'] = args
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   432
                break
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   433
            else:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   434
                wireargs[k] = args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   435
                del args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   436
        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
   437
            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
   438
            if isinstance(v, dict):
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   439
                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
   440
                    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
   441
                    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
   442
            else:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   443
                self._pipeo.write(v)
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   444
        self._pipeo.flush()
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   445
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   446
        return self._pipei
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   447
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
   448
    def _callcompressable(self, cmd, **args):
167047ba3cfa wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20794
diff changeset
   449
        return self._callstream(cmd, **args)
167047ba3cfa wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20794
diff changeset
   450
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   451
    def _call(self, cmd, **args):
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   452
        self._callstream(cmd, **args)
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   453
        return self._recv()
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   454
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   455
    def _callpush(self, cmd, fp, **args):
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   456
        r = self._call(cmd, **args)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   457
        if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   458
            return '', r
29739
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
   459
        for d in iter(lambda: fp.read(4096), ''):
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   460
            self._send(d)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   461
        self._send("", flush=True)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   462
        r = self._recv()
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   463
        if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   464
            return '', r
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   465
        return self._recv(), ''
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   466
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   467
    def _calltwowaystream(self, cmd, fp, **args):
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   468
        r = self._call(cmd, **args)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   469
        if r:
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   470
            # XXX needs to be made better
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 28438
diff changeset
   471
            raise error.Abort(_('unexpected remote reply: %s') % r)
29739
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
   472
        for d in iter(lambda: fp.read(4096), ''):
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   473
            self._send(d)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   474
        self._send("", flush=True)
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   475
        return self._pipei
11591
0d9cb3f3b0a1 protocol: unify client changegroup methods
Matt Mackall <mpm@selenic.com>
parents: 11590
diff changeset
   476
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   477
    def _getamount(self):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   478
        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
   479
        if l == '\n':
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   480
            self._readerr()
25243
d65243d28749 sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23684
diff changeset
   481
            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
   482
            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
   483
        self._readerr()
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
   484
        try:
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   485
            return int(l)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13827
diff changeset
   486
        except ValueError:
11590
0b15aee0a306 protocol: convert some ssh abort calls
Matt Mackall <mpm@selenic.com>
parents: 11589
diff changeset
   487
            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
   488
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   489
    def _recv(self):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   490
        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
   491
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   492
    def _send(self, data, flush=False):
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   493
        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
   494
        if data:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   495
            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
   496
        if flush:
33789
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   497
            self._pipeo.flush()
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33763
diff changeset
   498
        self._readerr()
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2549
diff changeset
   499
35968
b0d2885c5945 sshpeer: make "instance" a function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35699
diff changeset
   500
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
   501
    """Create an SSH peer.
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
   502
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
   503
    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
   504
    """
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
   505
    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
   506
    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
   507
        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
   508
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
   509
    util.checksafessh(path)
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
   510
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35968
diff changeset
   511
    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
   512
        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
   513
35972
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
   514
    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
   515
    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
   516
    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
   517
    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
   518
    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
   519
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
   520
    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
   521
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
   522
    if create:
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35971
diff changeset
   523
        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
   524
            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
   525
                (_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
   526
        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
   527
        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
   528
        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
   529
            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
   530
35975
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   531
    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
   532
                                                  remotepath, sshenv)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35974
diff changeset
   533
35978
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   534
    try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   535
        caps = _performhandshake(ui, stdin, stdout, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   536
    except Exception:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   537
        _cleanuppipes(ui, stdout, stdin, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   538
        raise
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   539
36016
625038cb4b1d sshpeer: rename sshpeer class to sshv1peer (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36015
diff changeset
   540
    return sshv1peer(ui, path, proc, stdin, stdout, stderr, caps)