mercurial/sshpeer.py
author Boris Feld <boris.feld@octobus.net>
Mon, 05 Feb 2018 17:35:14 +0100
changeset 35972 82afb1a5ed94
parent 35940 556218e08e25
child 35976 48a3a9283f09
permissions -rw-r--r--
revlog: use context manager for data file lifetime in checksize This is clearer, safer and more modern.
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
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    11
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    12
from .i18n import _
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    13
from . import (
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    14
    error,
33100
05906b8e1d23 py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32062
diff changeset
    15
    pycompat,
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    16
    util,
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    17
    wireproto,
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    18
)
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
    19
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
    20
def _serverquote(s):
35459
b520c8f98e1e sshpeer: move docstring to top
Yuya Nishihara <yuya@tcha.org>
parents: 35436
diff changeset
    21
    """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
    22
    if not s:
e3f30068d2eb sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents: 22935
diff changeset
    23
        return s
15624
be43234a6d60 sshrepo: add more safe characters (issue2983)
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15622
diff changeset
    24
    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
    25
        return s
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
    26
    return "'%s'" % s.replace("'", "'\\''")
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
    27
25244
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    28
def _forwardoutput(ui, pipe):
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    29
    """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
    30
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    31
    This is non blocking."""
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    32
    s = util.readpipe(pipe)
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    33
    if s:
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    34
        for l in s.splitlines():
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    35
            ui.status(_("remote: "), l, '\n')
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    36
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    37
class doublepipe(object):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    38
    """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
    39
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    40
    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
    41
    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
    42
    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
    43
    call on the "main" pipe.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    44
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    45
    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
    46
    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
    47
    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
    48
    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
    49
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    50
    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: 31197
diff changeset
    51
    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
    52
    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
    53
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    54
    def __init__(self, ui, main, side):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    55
        self._ui = ui
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    56
        self._main = main
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    57
        self._side = side
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    58
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    59
    def _wait(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    60
        """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
    61
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    62
        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
    63
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    64
        (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
    65
        """
25457
2afa748138e0 sshpeer: allow doublepipe on unbuffered main pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25456
diff changeset
    66
        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
    67
            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
    68
        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
    69
        try:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    70
            act = util.poll(fds)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    71
        except NotImplementedError:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    72
            # 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
    73
            act = fds
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    74
        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
    75
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
    76
    def write(self, data):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
    77
        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
    78
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    79
    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
    80
        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
    81
        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
    82
            # 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
    83
            # 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
    84
            # 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
    85
            # 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
    86
            # closed prematurely.
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
    87
            _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
    88
        return r
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    89
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    90
    def readline(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    91
        return self._call('readline')
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    92
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
    93
    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
    94
        """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
    95
        """
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
    96
        # 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
    97
        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
    98
            _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    99
            return ''
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   100
        while True:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   101
            mainready, sideready = self._wait()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   102
            if sideready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   103
                _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   104
            if mainready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   105
                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
   106
                if data is None:
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   107
                    return meth()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   108
                else:
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
   109
                    return meth(data)
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   110
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   111
    def close(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   112
        return self._main.close()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   113
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   114
    def flush(self):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   115
        return self._main.flush()
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   116
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   117
def _cleanuppipes(ui, pipei, pipeo, pipee):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   118
    """Clean up pipes used by an SSH connection."""
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   119
    if pipeo:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   120
        pipeo.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   121
    if pipei:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   122
        pipei.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   123
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   124
    if pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   125
        # 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: 35932
diff changeset
   126
        try:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   127
            for l in pipee:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   128
                ui.status(_('remote: '), l)
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   129
        except (IOError, ValueError):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   130
            pass
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   131
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   132
        pipee.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   133
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   134
def _makeconnection(ui, sshcmd, args, remotecmd, path, sshenv=None):
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   135
    """Create an SSH connection to a server.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   136
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   137
    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: 35934
diff changeset
   138
    spawned process.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   139
    """
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   140
    cmd = '%s %s %s' % (
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   141
        sshcmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   142
        args,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   143
        util.shellquote('%s -R %s serve --stdio' % (
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   144
            _serverquote(remotecmd), _serverquote(path))))
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   145
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   146
    ui.debug('running %s\n' % cmd)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   147
    cmd = util.quotecommand(cmd)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   148
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   149
    # no buffer allow the use of 'select'
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   150
    # 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: 35934
diff changeset
   151
    # move to threading.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   152
    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: 35934
diff changeset
   153
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   154
    stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   155
    stdin = doublepipe(ui, stdin, stderr)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   156
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   157
    return proc, stdin, stdout, stderr
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   158
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   159
def _performhandshake(ui, stdin, stdout, stderr):
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   160
    def badresponse():
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   161
        msg = _('no suitable response from remote hg')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   162
        hint = ui.config('ui', 'ssherrorhint')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   163
        raise error.RepoError(msg, hint=hint)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   164
35939
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   165
    # The handshake consists of sending 2 wire protocol commands:
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   166
    # ``hello`` and ``between``.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   167
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   168
    # The ``hello`` command (which was introduced in Mercurial 0.9.1)
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   169
    # instructs the server to advertise its capabilities.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   170
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   171
    # The ``between`` command (which has existed in all Mercurial servers
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   172
    # for as long as SSH support has existed), asks for the set of revisions
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   173
    # between a pair of revisions.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   174
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   175
    # The ``between`` command is issued with a request for the null
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   176
    # range. If the remote is a Mercurial server, this request will
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   177
    # generate a specific response: ``1\n\n``. This represents the
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   178
    # 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: 35938
diff changeset
   179
    # 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: 35938
diff changeset
   180
    # and we're at the end of our handshake reply.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   181
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   182
    # 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: 35938
diff changeset
   183
    # length of the value returned by that command followed by that
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   184
    # value. If the server doesn't support ``hello`` (which should be
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   185
    # 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: 35938
diff changeset
   186
    # RFC 822 like lines. Of these, the ``capabilities:`` line contains
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   187
    # the capabilities of the server.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   188
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   189
    # In addition to the responses to our command requests, the server
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   190
    # may emit "banner" output on stdout. SSH servers are allowed to
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   191
    # print messages to stdout on login. Issuing commands on connection
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   192
    # 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: 35938
diff changeset
   193
    # for output to our well-known ``between`` command. Of course, if
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   194
    # 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: 35938
diff changeset
   195
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   196
    requestlog = ui.configbool('devel', 'debug.peer-request')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   197
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   198
    try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   199
        pairsarg = '%s-%s' % ('0' * 40, '0' * 40)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   200
        handshake = [
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   201
            'hello\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   202
            'between\n',
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   203
            'pairs %d\n' % len(pairsarg),
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   204
            pairsarg,
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   205
        ]
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   206
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   207
        if requestlog:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   208
            ui.debug('devel-peer-request: hello\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   209
        ui.debug('sending hello command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   210
        if requestlog:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   211
            ui.debug('devel-peer-request: between\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   212
            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: 35937
diff changeset
   213
        ui.debug('sending between command\n')
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   214
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   215
        stdin.write(''.join(handshake))
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   216
        stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   217
    except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   218
        badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   219
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   220
    lines = ['', 'dummy']
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   221
    max_noise = 500
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   222
    while lines[-1] and max_noise:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   223
        try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   224
            l = stdout.readline()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   225
            _forwardoutput(ui, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   226
            if lines[-1] == '1\n' and l == '\n':
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   227
                break
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   228
            if l:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   229
                ui.debug('remote: ', l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   230
            lines.append(l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   231
            max_noise -= 1
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   232
        except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   233
            badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   234
    else:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   235
        badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   236
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   237
    caps = set()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   238
    for l in reversed(lines):
35939
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   239
        # Look for response to ``hello`` command. Scan from the back so
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   240
        # we don't misinterpret banner output as the command reply.
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   241
        if l.startswith('capabilities:'):
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   242
            caps.update(l[:-1].split(':')[1].split())
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   243
            break
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   244
35940
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   245
    # Error if we couldn't find a response to ``hello``. This could
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   246
    # mean:
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   247
    #
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   248
    # 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: 35939
diff changeset
   249
    # 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: 35939
diff changeset
   250
    # 3. Remote is a future Mercurial server that dropped ``hello``
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   251
    #    support.
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   252
    if not caps:
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   253
        badresponse()
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   254
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   255
    return caps
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   256
17192
1ac628cd7113 peer: introduce real peer classes
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 16688
diff changeset
   257
class sshpeer(wireproto.wirepeer):
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   258
    def __init__(self, ui, url, proc, stdin, stdout, stderr, caps):
35936
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   259
        """Create a peer from an existing SSH connection.
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   260
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   261
        ``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: 35935
diff changeset
   262
        ``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: 35935
diff changeset
   263
        pipes for that process.
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   264
        ``caps`` is a set of capabilities supported by the remote.
35936
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   265
        """
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   266
        self._url = url
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   267
        self._ui = ui
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   268
        # 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: 35934
diff changeset
   269
        # holds a reference and prevents it from being garbage collected.
35936
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   270
        self._subprocess = proc
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   271
        self._pipeo = stdin
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   272
        self._pipei = stdout
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   273
        self._pipee = stderr
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   274
        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
   275
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   276
    # Begin of _basepeer interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   277
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   278
    @util.propertycache
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   279
    def ui(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   280
        return self._ui
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   281
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   282
    def url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   283
        return self._url
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   284
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   285
    def local(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   286
        return None
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   287
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   288
    def peer(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   289
        return self
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   290
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   291
    def canpush(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   292
        return True
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   293
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   294
    def close(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   295
        pass
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   296
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   297
    # End of _basepeer interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   298
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   299
    # Begin of _basewirecommands interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   300
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   301
    def capabilities(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   302
        return self._caps
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   303
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   304
    # End of _basewirecommands interface.
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   305
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   306
    def _readerr(self):
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   307
        _forwardoutput(self.ui, self._pipee)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   308
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   309
    def _abort(self, exception):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   310
        self._cleanup()
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   311
        raise exception
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   312
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   313
    def _cleanup(self):
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   314
        _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
   315
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   316
    __del__ = _cleanup
3034
2b0bc36a48d8 sshrepo: flush stderr before connecting to the hg server
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
   317
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   318
    def _submitbatch(self, req):
29733
bb04f96df51c wireproto: consolidate code for obtaining "cmds" argument value
Gregory Szorc <gregory.szorc@gmail.com>
parents: 29727
diff changeset
   319
        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
   320
        available = self._getamount()
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   321
        # 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
   322
        # batches with large responses.
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   323
        toread = min(available, 1024)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   324
        work = rsp.read(toread)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   325
        available -= toread
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   326
        chunk = work
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   327
        while chunk:
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   328
            while ';' in work:
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   329
                one, work = work.split(';', 1)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   330
                yield wireproto.unescapearg(one)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   331
            toread = min(available, 1024)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   332
            chunk = rsp.read(toread)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   333
            available -= toread
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   334
            work += chunk
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   335
        yield wireproto.unescapearg(work)
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   336
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   337
    def _callstream(self, cmd, **args):
33100
05906b8e1d23 py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32062
diff changeset
   338
        args = pycompat.byteskwargs(args)
35699
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   339
        if (self.ui.debugflag
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   340
            and self.ui.configbool('devel', 'debug.peer-request')):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   341
            dbg = self.ui.debug
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   342
            line = 'devel-peer-request: %s\n'
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   343
            dbg(line % cmd)
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   344
            for key, value in sorted(args.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   345
                if not isinstance(value, dict):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   346
                    dbg(line % '  %s: %d bytes' % (key, len(value)))
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   347
                else:
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   348
                    for dk, dv in sorted(value.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   349
                        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
   350
        self.ui.debug("sending %s command\n" % cmd)
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   351
        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
   352
        _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
   353
        keys = names.split()
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   354
        wireargs = {}
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   355
        for k in keys:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   356
            if k == '*':
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   357
                wireargs['*'] = args
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   358
                break
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   359
            else:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   360
                wireargs[k] = args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   361
                del args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   362
        for k, v in sorted(wireargs.iteritems()):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   363
            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
   364
            if isinstance(v, dict):
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   365
                for dk, dv in v.iteritems():
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   366
                    self._pipeo.write("%s %d\n" % (dk, len(dv)))
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   367
                    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
   368
            else:
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   369
                self._pipeo.write(v)
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   370
        self._pipeo.flush()
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   371
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   372
        return self._pipei
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   373
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
   374
    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
   375
        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
   376
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   377
    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
   378
        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
   379
        return self._recv()
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   380
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   381
    def _callpush(self, cmd, fp, **args):
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   382
        r = self._call(cmd, **args)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   383
        if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   384
            return '', r
29727
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
   385
        for d in iter(lambda: fp.read(4096), ''):
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   386
            self._send(d)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   387
        self._send("", flush=True)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   388
        r = self._recv()
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   389
        if r:
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   390
            return '', r
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   391
        return self._recv(), ''
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   392
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   393
    def _calltwowaystream(self, cmd, fp, **args):
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   394
        r = self._call(cmd, **args)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   395
        if r:
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   396
            # XXX needs to be made better
29389
98e8313dcd9e i18n: translate abort messages
liscju <piotr.listkiewicz@gmail.com>
parents: 28438
diff changeset
   397
            raise error.Abort(_('unexpected remote reply: %s') % r)
29727
0dbd788a2dfd sshpeer: use `iter(callable, sentinel)` instead of while True
Augie Fackler <augie@google.com>
parents: 29389
diff changeset
   398
        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
   399
            self._send(d)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   400
        self._send("", flush=True)
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   401
        return self._pipei
11591
0d9cb3f3b0a1 protocol: unify client changegroup methods
Matt Mackall <mpm@selenic.com>
parents: 11590
diff changeset
   402
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   403
    def _getamount(self):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   404
        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
   405
        if l == '\n':
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   406
            self._readerr()
25243
d65243d28749 sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23684
diff changeset
   407
            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
   408
            self._abort(error.OutOfBandError(hint=msg))
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   409
        self._readerr()
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
   410
        try:
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   411
            return int(l)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13827
diff changeset
   412
        except ValueError:
11590
0b15aee0a306 protocol: convert some ssh abort calls
Matt Mackall <mpm@selenic.com>
parents: 11589
diff changeset
   413
            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
   414
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   415
    def _recv(self):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   416
        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
   417
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   418
    def _send(self, data, flush=False):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   419
        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
   420
        if data:
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   421
            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
   422
        if flush:
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   423
            self._pipeo.flush()
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   424
        self._readerr()
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2549
diff changeset
   425
35928
b0d2885c5945 sshpeer: make "instance" a function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35699
diff changeset
   426
def instance(ui, path, create):
35931
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   427
    """Create an SSH peer.
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   428
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   429
    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: 35928
diff changeset
   430
    """
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   431
    u = util.url(path, parsequery=False, parsefragment=False)
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   432
    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: 35928
diff changeset
   433
        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: 35928
diff changeset
   434
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   435
    util.checksafessh(path)
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   436
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   437
    if u.passwd is not None:
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   438
        raise error.RepoError(_('password in URL not supported'))
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   439
35932
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   440
    sshcmd = ui.config('ui', 'ssh')
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   441
    remotecmd = ui.config('ui', 'remotecmd')
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   442
    sshaddenv = dict(ui.configitems('sshenv'))
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   443
    sshenv = util.shellenviron(sshaddenv)
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   444
    remotepath = u.path or '.'
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   445
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   446
    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: 35931
diff changeset
   447
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   448
    if create:
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   449
        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: 35931
diff changeset
   450
            util.shellquote('%s init %s' %
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   451
                (_serverquote(remotecmd), _serverquote(remotepath))))
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   452
        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: 35931
diff changeset
   453
        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: 35931
diff changeset
   454
        if res != 0:
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   455
            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: 35931
diff changeset
   456
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   457
    proc, stdin, stdout, stderr = _makeconnection(ui, sshcmd, args, remotecmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   458
                                                  remotepath, sshenv)
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   459
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   460
    try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   461
        caps = _performhandshake(ui, stdin, stdout, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   462
    except Exception:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   463
        _cleanuppipes(ui, stdout, stdin, stderr)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   464
        raise
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   465
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   466
    return sshpeer(ui, path, proc, stdin, stdout, stderr, caps)