mercurial/sshpeer.py
author Joerg Sonnenberger <joerg@bec.de>
Fri, 30 Apr 2021 02:11:58 +0200
changeset 47043 12450fbea288
parent 46907 ffd3e823a7e5
child 48526 04688c51f81f
permissions -rw-r--r--
manifests: push down expected node length into the parser This strictly enforces the node length in the manifest lines according to what the repository expects. One test case moves large hash testing into the non-treemanifest part as treemanifests don't provide an interface for overriding just the node length for now. Differential Revision: https://phab.mercurial-scm.org/D10533
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
#
46819
d4ba4d51f85f contributor: change mentions of mpm to olivia
Raphaël Gomès <rgomes@octobus.net>
parents: 46671
diff changeset
     3
# Copyright 2005, 2006 Olivia Mackall <olivia@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
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
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 _
43089
c59eb1560c44 py3: manually import getattr where it is needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
    14
from .pycompat import getattr
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    15
from . import (
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    16
    error,
33100
05906b8e1d23 py3: use pycompat.byteskwargs() to convert kwargs' keys to bytes
Pulkit Goyal <7895pulkit@gmail.com>
parents: 32062
diff changeset
    17
    pycompat,
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    18
    util,
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
    19
    wireprotoserver,
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36533
diff changeset
    20
    wireprototypes,
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
    21
    wireprotov1peer,
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37717
diff changeset
    22
    wireprotov1server,
25975
de7a3893ee65 sshpeer: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25458
diff changeset
    23
)
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
    24
from .utils import (
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
    25
    procutil,
38475
67dc32d4e790 cleanup: migrate from re.escape to stringutil.reescape
Augie Fackler <augie@google.com>
parents: 37813
diff changeset
    26
    stringutil,
46907
ffd3e823a7e5 urlutil: extract `url` related code from `util` into the new module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
    27
    urlutil,
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
    28
)
60
e32fdbd97839 Add hg:// protocol
mpm@selenic.com
parents: 56
diff changeset
    29
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    30
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
    31
def _serverquote(s):
35459
b520c8f98e1e sshpeer: move docstring to top
Yuya Nishihara <yuya@tcha.org>
parents: 35436
diff changeset
    32
    """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
    33
    if not s:
e3f30068d2eb sshpeer: more thorough shell quoting
Matt Mackall <mpm@selenic.com>
parents: 22935
diff changeset
    34
        return s
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    35
    if re.match(b'[a-zA-Z0-9@%_+=:,./-]*$', s):
15622
86fc364ca5f8 sshrepo: don't quote obviously safe strings (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15581
diff changeset
    36
        return s
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    37
    return b"'%s'" % s.replace(b"'", b"'\\''")
15581
d8fa35c28335 ssh: quote remote paths (issue2983)
Mads Kiilerich <mads@kiilerich.com>
parents: 15017
diff changeset
    38
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    39
44860
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
    40
def _forwardoutput(ui, pipe, warn=False):
25244
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    41
    """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
    42
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    43
    This is non blocking."""
46671
fa30292b680b sshpeer: don't fail forwarding output from closed connections
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 46663
diff changeset
    44
    if pipe and not pipe.closed:
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
    45
        s = procutil.readpipe(pipe)
36833
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36628
diff changeset
    46
        if s:
44860
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
    47
            display = ui.warn if warn else ui.status
36833
46f4d71ed505 sshpeer: check pipe validity before forwarding output from it
Matt Harbison <matt_harbison@yahoo.com>
parents: 36628
diff changeset
    48
            for l in s.splitlines():
44860
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
    49
                display(_(b"remote: "), l, b'\n')
25244
cf90764f40a4 sshpeer: extract the forward output logic
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25243
diff changeset
    50
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    51
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    52
class doublepipe(object):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    53
    """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
    54
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    55
    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
    56
    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
    57
    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
    58
    call on the "main" pipe.
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    59
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    60
    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
    61
    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
    62
    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
    63
    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
    64
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    65
    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
    66
    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
    67
    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
    68
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    69
    def __init__(self, ui, main, side):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    70
        self._ui = ui
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    71
        self._main = main
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    72
        self._side = side
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    73
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    74
    def _wait(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    75
        """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
    76
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    77
        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
    78
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    79
        (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
    80
        """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    81
        if (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    82
            isinstance(self._main, util.bufferedinputpipe)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    83
            and self._main.hasbuffer
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
    84
        ):
36369
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36367
diff changeset
    85
            # Main has data. Assume side is worth poking at.
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36367
diff changeset
    86
            return True, True
066e6a9d52bb sshpeer: make pipe polling code more explicit
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36367
diff changeset
    87
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    88
        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
    89
        try:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    90
            act = util.poll(fds)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    91
        except NotImplementedError:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    92
            # 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
    93
            act = fds
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    94
        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
    95
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
    96
    def write(self, data):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    97
        return self._call(b'write', data)
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
    98
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
    99
    def read(self, size):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   100
        r = self._call(b'read', size)
32062
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
   101
        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
   102
            # 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
   103
            # 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
   104
            # 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
   105
            # 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
   106
            # closed prematurely.
ad6c5497cd15 sshpeer: try harder to snag stderr when stdout closes unexpectedly
Augie Fackler <augie@google.com>
parents: 31953
diff changeset
   107
            _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
   108
        return r
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   109
38713
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   110
    def unbufferedread(self, size):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   111
        r = self._call(b'unbufferedread', size)
38713
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   112
        if size != 0 and not r:
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   113
            # We've observed a condition that indicates the
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   114
            # stdout closed unexpectedly. Check stderr one
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   115
            # more time and snag anything that's there before
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   116
            # letting anyone know the main part of the pipe
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   117
            # closed prematurely.
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   118
            _forwardoutput(self._ui, self._side)
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   119
        return r
27391d74aaa2 ssh: avoid reading beyond the end of stream when using compression
Joerg Sonnenberger <joerg@bec.de>
parents: 38475
diff changeset
   120
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   121
    def readline(self):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   122
        return self._call(b'readline')
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   123
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
   124
    def _call(self, methname, data=None):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 44867
diff changeset
   125
        """call <methname> on "main", forward output of "side" while blocking"""
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
   126
        # 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
   127
        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
   128
            _forwardoutput(self._ui, self._side)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   129
            return b''
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   130
        while True:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   131
            mainready, sideready = self._wait()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   132
            if sideready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   133
                _forwardoutput(self._ui, self._side)
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   134
            if mainready:
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   135
                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
   136
                if data is None:
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   137
                    return meth()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   138
                else:
25455
dc02a284e034 sshpeer: rename 'size' to 'data' in doublepipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25422
diff changeset
   139
                    return meth(data)
25421
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   140
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   141
    def close(self):
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   142
        return self._main.close()
3dd3ccf7b807 sshpeer: introduce a "doublepipe" class
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25408
diff changeset
   143
46660
0738bc25d6ac sshpeer: add a method to check if a doublepipe is closed
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46659
diff changeset
   144
    @property
0738bc25d6ac sshpeer: add a method to check if a doublepipe is closed
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46659
diff changeset
   145
    def closed(self):
0738bc25d6ac sshpeer: add a method to check if a doublepipe is closed
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46659
diff changeset
   146
        return self._main.closed
0738bc25d6ac sshpeer: add a method to check if a doublepipe is closed
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46659
diff changeset
   147
25456
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   148
    def flush(self):
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   149
        return self._main.flush()
408b7979bf03 sshpeer: allow write operations through double pipe
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 25455
diff changeset
   150
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   151
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   152
def _cleanuppipes(ui, pipei, pipeo, pipee, warn):
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   153
    """Clean up pipes used by an SSH connection."""
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   154
    didsomething = False
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   155
    if pipeo and not pipeo.closed:
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   156
        didsomething = True
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   157
        pipeo.close()
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   158
    if pipei and not pipei.closed:
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   159
        didsomething = True
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   160
        pipei.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   161
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   162
    if pipee and not pipee.closed:
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   163
        didsomething = True
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   164
        # 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
   165
        try:
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   166
            for l in pipee:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   167
                ui.status(_(b'remote: '), l)
35933
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   168
        except (IOError, ValueError):
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   169
            pass
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   170
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   171
        pipee.close()
805edf16e8e0 sshpeer: extract pipe cleanup logic to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35932
diff changeset
   172
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   173
    if didsomething and warn is not None:
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   174
        # Encourage explicit close of sshpeers. Closing via __del__ is
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   175
        # not very predictable when exceptions are thrown, which has led
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   176
        # to deadlocks due to a peer get gc'ed in a fork
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   177
        # We add our own stack trace, because the stacktrace when called
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   178
        # from __del__ is useless.
46663
a4c19a162615 sshpeer: enable+fix warning about sshpeers not being closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46662
diff changeset
   179
        ui.develwarn(b'missing close on SSH connection created at:\n%s' % warn)
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   180
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   181
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   182
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
   183
    """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
   184
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   185
    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
   186
    spawned process.
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   187
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   188
    cmd = b'%s %s %s' % (
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   189
        sshcmd,
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   190
        args,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   191
        procutil.shellquote(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   192
            b'%s -R %s serve --stdio'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   193
            % (_serverquote(remotecmd), _serverquote(path))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   194
        ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   195
    )
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   196
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   197
    ui.debug(b'running %s\n' % cmd)
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   198
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   199
    # 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
   200
    # 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
   201
    # move to threading.
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
   202
    stdin, stdout, stderr, proc = procutil.popen4(cmd, bufsize=0, env=sshenv)
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   203
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   204
    return proc, stdin, stdout, stderr
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   205
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   206
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   207
def _clientcapabilities():
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   208
    """Return list of capabilities of this client.
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   209
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   210
    Returns a list of capabilities that are supported by this client.
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   211
    """
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   212
    protoparams = {b'partial-pull'}
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   213
    comps = [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   214
        e.wireprotosupport().name
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   215
        for e in util.compengines.supportedwireengines(util.CLIENTROLE)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   216
    ]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   217
    protoparams.add(b'comp=%s' % b','.join(comps))
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   218
    return protoparams
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   219
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   220
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   221
def _performhandshake(ui, stdin, stdout, stderr):
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   222
    def badresponse():
44860
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   223
        # Flush any output on stderr. In general, the stderr contains errors
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   224
        # from the remote (ssh errors, some hg errors), and status indications
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   225
        # (like "adding changes"), with no current way to tell them apart.
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   226
        # Here we failed so early that it's almost certainly only errors, so
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   227
        # use warn=True so -q doesn't hide them.
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   228
        _forwardoutput(ui, stderr, warn=True)
36370
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   229
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   230
        msg = _(b'no suitable response from remote hg')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   231
        hint = ui.config(b'ui', b'ssherrorhint')
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   232
        raise error.RepoError(msg, hint=hint)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   233
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   234
    # 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: 35940
diff changeset
   235
    # 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: 35940
diff changeset
   236
    # to one of them.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   237
    #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   238
    # Those commands (from oldest to newest) are:
35939
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   239
    #
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   240
    # ``between``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   241
    #   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: 35940
diff changeset
   242
    #   present in all Mercurial server implementations.
35939
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   243
    #
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   244
    # ``hello``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   245
    #   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: 35940
diff changeset
   246
    #   Mercurial 0.9.1.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   247
    #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   248
    # ``upgrade``
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   249
    #   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: 35940
diff changeset
   250
    #   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: 35940
diff changeset
   251
    #   feature.
35939
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   252
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   253
    # 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
   254
    # 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
   255
    # 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
   256
    # 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
   257
    # 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
   258
    # 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
   259
    #
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   260
    # 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
   261
    # 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
   262
    # 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
   263
    # 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
   264
    # 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
   265
    # the capabilities of the server.
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   266
    #
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   267
    # 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: 35940
diff changeset
   268
    # 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: 35940
diff changeset
   269
    # 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: 35940
diff changeset
   270
    # arguments on the line, delimited by spaces.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   271
    #
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   272
    # 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: 35940
diff changeset
   273
    # 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: 35940
diff changeset
   274
    # 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: 35940
diff changeset
   275
    # ``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: 35940
diff changeset
   276
    # Content immediately following this line describes additional
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   277
    # protocol and server state.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   278
    #
35939
a622a927fe03 sshpeer: document the handshake mechanism
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35938
diff changeset
   279
    # 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
   280
    # 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
   281
    # 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
   282
    # 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
   283
    # 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
   284
    # 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
   285
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   286
    requestlog = ui.configbool(b'devel', b'debug.peer-request')
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   287
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   288
    # 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: 35940
diff changeset
   289
    # upgrade request.
36043
223ed0b53f08 py3: more robustly cast UUID to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35978
diff changeset
   290
    token = pycompat.sysbytes(str(uuid.uuid4()))
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   291
    upgradecaps = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   292
        (b'proto', wireprotoserver.SSHV2),
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   293
    ]
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   294
    upgradecaps = util.urlreq.urlencode(upgradecaps)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   295
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   296
    try:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   297
        pairsarg = b'%s-%s' % (b'0' * 40, b'0' * 40)
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   298
        handshake = [
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   299
            b'hello\n',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   300
            b'between\n',
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   301
            b'pairs %d\n' % len(pairsarg),
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   302
            pairsarg,
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   303
        ]
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   304
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   305
        # Request upgrade to version 2 if configured.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   306
        if ui.configbool(b'experimental', b'sshpeer.advertise-v2'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   307
            ui.debug(b'sending upgrade request: %s %s\n' % (token, upgradecaps))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   308
            handshake.insert(0, b'upgrade %s %s\n' % (token, upgradecaps))
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   309
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   310
        if requestlog:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   311
            ui.debug(b'devel-peer-request: hello+between\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   312
            ui.debug(b'devel-peer-request:   pairs: %d bytes\n' % len(pairsarg))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   313
        ui.debug(b'sending hello command\n')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   314
        ui.debug(b'sending between command\n')
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   315
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   316
        stdin.write(b''.join(handshake))
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   317
        stdin.flush()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   318
    except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   319
        badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   320
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   321
    # Assume version 1 of wire protocol by default.
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36533
diff changeset
   322
    protoname = wireprototypes.SSHV1
38475
67dc32d4e790 cleanup: migrate from re.escape to stringutil.reescape
Augie Fackler <augie@google.com>
parents: 37813
diff changeset
   323
    reupgraded = re.compile(b'^upgraded %s (.*)$' % stringutil.reescape(token))
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   324
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   325
    lines = [b'', b'dummy']
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   326
    max_noise = 500
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   327
    while lines[-1] and max_noise:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   328
        try:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   329
            l = stdout.readline()
44860
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   330
            _forwardoutput(ui, stderr, warn=True)
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   331
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   332
            # 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: 35940
diff changeset
   333
            # 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: 35940
diff changeset
   334
            m = reupgraded.match(l)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   335
            if m:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   336
                protoname = m.group(1)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   337
                ui.debug(b'protocol upgraded to %s\n' % protoname)
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   338
                # 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: 35940
diff changeset
   339
                # 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: 35940
diff changeset
   340
                # protocol, so stop scanning lines.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   341
                break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   342
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   343
            # 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: 35940
diff changeset
   344
            # doesn't support upgrade.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   345
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   346
            if lines[-1] == b'1\n' and l == b'\n':
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   347
                break
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   348
            if l:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   349
                ui.debug(b'remote: ', l)
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   350
            lines.append(l)
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   351
            max_noise -= 1
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   352
        except IOError:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   353
            badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   354
    else:
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   355
        badresponse()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   356
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   357
    caps = set()
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   358
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   359
    # 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: 35940
diff changeset
   360
    # ``hello`` command.
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36533
diff changeset
   361
    if protoname == wireprototypes.SSHV1:
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   362
        for l in reversed(lines):
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   363
            # 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: 35940
diff changeset
   364
            # we don't misinterpret banner output as the command reply.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   365
            if l.startswith(b'capabilities:'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   366
                caps.update(l[:-1].split(b':')[1].split())
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   367
                break
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   368
    elif protoname == wireprotoserver.SSHV2:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   369
        # 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: 35940
diff changeset
   370
        # looking like ``capabilities: *``.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   371
        line = stdout.readline()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   372
        try:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   373
            valuelen = int(line)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   374
        except ValueError:
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   375
            badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   376
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   377
        capsline = stdout.read(valuelen)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   378
        if not capsline.startswith(b'capabilities: '):
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   379
            badresponse()
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   380
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   381
        ui.debug(b'remote: %s\n' % capsline)
36216
7218e93ade47 sshpeer: log remote capabilities after protocol upgrade
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36043
diff changeset
   382
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   383
        caps.update(capsline.split(b':')[1].split())
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   384
        # Trailing newline.
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   385
        stdout.read(1)
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   386
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   387
    # Error if we couldn't find capabilities, this means:
35940
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   388
    #
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   389
    # 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
   390
    # 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
   391
    # 3. Remote is a future Mercurial server that dropped ``hello``
35976
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
   392
    #    and other attempted handshake mechanisms.
35940
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   393
    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
   394
        badresponse()
556218e08e25 sshpeer: remove support for connecting to <0.9.1 servers (BC)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35939
diff changeset
   395
36370
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   396
    # Flush any output on stderr before proceeding.
44860
5d77f571a563 sshpeer: make client print (likely) server errors on stderr (BC)
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 43106
diff changeset
   397
    _forwardoutput(ui, stderr, warn=True)
36370
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   398
35978
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   399
    return protoname, caps
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   400
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   401
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
   402
class sshv1peer(wireprotov1peer.wirepeer):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   403
    def __init__(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   404
        self, ui, url, proc, stdin, stdout, stderr, caps, autoreadstderr=True
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   405
    ):
35936
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   406
        """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
   407
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   408
        ``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
   409
        ``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
   410
        pipes for that process.
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   411
        ``caps`` is a set of capabilities supported by the remote.
36533
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36487
diff changeset
   412
        ``autoreadstderr`` denotes whether to automatically read from
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36487
diff changeset
   413
        stderr and to forward its output.
35936
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   414
        """
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   415
        self._url = url
37321
e826fe7a08c7 peer: make ui an attribute
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37320
diff changeset
   416
        self.ui = ui
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   417
        # 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
   418
        # 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
   419
        self._subprocess = proc
36370
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   420
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   421
        # And we hook up our "doublepipe" wrapper to allow querying
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   422
        # stderr any time we perform I/O.
36533
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36487
diff changeset
   423
        if autoreadstderr:
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36487
diff changeset
   424
            stdout = doublepipe(ui, util.bufferedinputpipe(stdout), stderr)
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36487
diff changeset
   425
            stdin = doublepipe(ui, stdin, stderr)
36370
11ba1a96f946 sshpeer: defer pipe buffering and stderr sidechannel binding
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36369
diff changeset
   426
35936
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   427
        self._pipeo = stdin
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   428
        self._pipei = stdout
f8f034344b39 sshpeer: clean up API for sshpeer.__init__ (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35935
diff changeset
   429
        self._pipee = stderr
35938
80a2b8ae42a1 sshpeer: move handshake outside of sshpeer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35937
diff changeset
   430
        self._caps = caps
36608
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   431
        self._autoreadstderr = autoreadstderr
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   432
        self._initstack = b''.join(util.getstackframes(1))
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
   433
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   434
    # Commands that have a "framed" response where the first line of the
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   435
    # response contains the length of that response.
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   436
    _FRAMED_COMMANDS = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   437
        b'batch',
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   438
    }
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   439
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37120
diff changeset
   440
    # Begin of ipeerconnection interface.
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   441
2673
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   442
    def url(self):
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   443
        return self._url
109a22f5434a hooks: add url to changegroup, incoming, prechangegroup, pretxnchangegroup hooks
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2612
diff changeset
   444
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   445
    def local(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   446
        return None
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   447
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   448
    def peer(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   449
        return self
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   450
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   451
    def canpush(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   452
        return True
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   453
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   454
    def close(self):
46659
8c4906105f37 sshpeer: make sshpeer.close() close the underlying connection
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 45942
diff changeset
   455
        self._cleanup()
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   456
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37120
diff changeset
   457
    # End of ipeerconnection interface.
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   458
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37120
diff changeset
   459
    # Begin of ipeercommands interface.
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   460
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   461
    def capabilities(self):
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   462
        return self._caps
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   463
37320
39f7d4ee8bcd repository: port peer interfaces to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37120
diff changeset
   464
    # End of ipeercommands interface.
33804
1f8460b55986 sshpeer: use peer interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33768
diff changeset
   465
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   466
    def _readerr(self):
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   467
        _forwardoutput(self.ui, self._pipee)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   468
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   469
    def _abort(self, exception):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   470
        self._cleanup()
11586
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   471
        raise exception
ddaaaa23bb8f protocol: move basic ssh client commands to wirerepository
Matt Mackall <mpm@selenic.com>
parents: 11369
diff changeset
   472
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   473
    def _cleanup(self, warn=None):
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   474
        _cleanuppipes(self.ui, self._pipei, self._pipeo, self._pipee, warn=warn)
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   475
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   476
    def __del__(self):
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   477
        self._cleanup(warn=self._initstack)
3034
2b0bc36a48d8 sshrepo: flush stderr before connecting to the hg server
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 2859
diff changeset
   478
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   479
    def _sendrequest(self, cmd, args, framed=False):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   480
        if self.ui.debugflag and self.ui.configbool(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   481
            b'devel', b'debug.peer-request'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   482
        ):
35699
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   483
            dbg = self.ui.debug
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   484
            line = b'devel-peer-request: %s\n'
35699
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   485
            dbg(line % cmd)
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   486
            for key, value in sorted(args.items()):
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   487
                if not isinstance(value, dict):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   488
                    dbg(line % b'  %s: %d bytes' % (key, len(value)))
35699
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   489
                else:
f7ef49e44d7c sshpeer: add support for request tracing
Boris Feld <boris.feld@octobus.net>
parents: 35459
diff changeset
   490
                    for dk, dv in sorted(value.items()):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   491
                        dbg(line % b'  %s-%s: %d' % (key, dk, len(dv)))
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   492
        self.ui.debug(b"sending %s command\n" % cmd)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   493
        self._pipeo.write(b"%s\n" % cmd)
37785
b4d85bc122bd wireproto: rename wireproto to wireprotov1server (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37717
diff changeset
   494
        _func, names = wireprotov1server.commands[cmd]
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   495
        keys = names.split()
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   496
        wireargs = {}
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   497
        for k in keys:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   498
            if k == b'*':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   499
                wireargs[b'*'] = args
13721
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   500
                break
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   501
            else:
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   502
                wireargs[k] = args[k]
3458c15ab2f0 wireproto: fix handling of '*' args for HTTP and SSH
Peter Arrenbrecht <peter.arrenbrecht@gmail.com>
parents: 13464
diff changeset
   503
                del args[k]
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   504
        for k, v in sorted(pycompat.iteritems(wireargs)):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   505
            self._pipeo.write(b"%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
   506
            if isinstance(v, dict):
43106
d783f945a701 py3: finish porting iteritems() to pycompat and remove source transformer
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43089
diff changeset
   507
                for dk, dv in pycompat.iteritems(v):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   508
                    self._pipeo.write(b"%s %d\n" % (dk, len(dv)))
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   509
                    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
   510
            else:
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   511
                self._pipeo.write(v)
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   512
        self._pipeo.flush()
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   513
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   514
        # We know exactly how many bytes are in the response. So return a proxy
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   515
        # around the raw output stream that allows reading exactly this many
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   516
        # bytes. Callers then can read() without fear of overrunning the
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   517
        # response.
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   518
        if framed:
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   519
            amount = self._getamount()
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   520
            return util.cappedreader(self._pipei, amount)
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   521
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   522
        return self._pipei
624
876333a295ff Add an sshrepository class and hg serve --stdio
Matt Mackall <mpm@selenic.com>
parents: 623
diff changeset
   523
36366
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36363
diff changeset
   524
    def _callstream(self, cmd, **args):
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36363
diff changeset
   525
        args = pycompat.byteskwargs(args)
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   526
        return self._sendrequest(cmd, args, framed=cmd in self._FRAMED_COMMANDS)
36366
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36363
diff changeset
   527
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
   528
    def _callcompressable(self, cmd, **args):
36366
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36363
diff changeset
   529
        args = pycompat.byteskwargs(args)
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   530
        return self._sendrequest(cmd, args, framed=cmd in self._FRAMED_COMMANDS)
20905
167047ba3cfa wireproto: drop the _decompress method in favor a new call type
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20794
diff changeset
   531
11589
e8d22fe2ddab protocol: clean up call-like functions in http and ssh clients
Matt Mackall <mpm@selenic.com>
parents: 11588
diff changeset
   532
    def _call(self, cmd, **args):
36366
a34d5ef53c2e sshpeer: move logic for sending a request into a new function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36363
diff changeset
   533
        args = pycompat.byteskwargs(args)
36367
043e77f3be09 sshpeer: return framed file object when needed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36366
diff changeset
   534
        return self._sendrequest(cmd, args, framed=True).read()
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   535
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   536
    def _callpush(self, cmd, fp, **args):
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   537
        # The server responds with an empty frame if the client should
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   538
        # continue submitting the payload.
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   539
        r = self._call(cmd, **args)
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   540
        if r:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   541
            return b'', r
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   542
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   543
        # The payload consists of frames with content followed by an empty
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   544
        # frame.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   545
        for d in iter(lambda: fp.read(4096), b''):
36363
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36216
diff changeset
   546
            self._writeframed(d)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   547
        self._writeframed(b"", flush=True)
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   548
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   549
        # In case of success, there is an empty frame and a frame containing
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   550
        # the integer result (as a string).
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   551
        # In case of error, there is a non-empty frame containing the error.
36363
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36216
diff changeset
   552
        r = self._readframed()
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   553
        if r:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   554
            return b'', r
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   555
        return self._readframed(), b''
11592
26e0782b8380 protocol: unify client unbundle support
Matt Mackall <mpm@selenic.com>
parents: 11591
diff changeset
   556
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   557
    def _calltwowaystream(self, cmd, fp, **args):
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   558
        # The server responds with an empty frame if the client should
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   559
        # continue submitting the payload.
21073
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   560
        r = self._call(cmd, **args)
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   561
        if r:
83ce71ef7804 sshpeer: add implementation of _calltwowaystream
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 20905
diff changeset
   562
            # XXX needs to be made better
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   563
            raise error.Abort(_(b'unexpected remote reply: %s') % r)
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   564
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   565
        # The payload consists of frames with content followed by an empty
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   566
        # frame.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   567
        for d in iter(lambda: fp.read(4096), b''):
36363
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36216
diff changeset
   568
            self._writeframed(d)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   569
        self._writeframed(b"", flush=True)
36372
b8d0761a85c7 wireproto: document the wonky push protocol for SSH
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36370
diff changeset
   570
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   571
        return self._pipei
11591
0d9cb3f3b0a1 protocol: unify client changegroup methods
Matt Mackall <mpm@selenic.com>
parents: 11590
diff changeset
   572
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   573
    def _getamount(self):
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   574
        l = self._pipei.readline()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   575
        if l == b'\n':
36608
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   576
            if self._autoreadstderr:
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   577
                self._readerr()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   578
            msg = _(b'check previous remote output')
25243
d65243d28749 sshpeer: break "OutOfBandError" feature for ssh (BC)
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 23684
diff changeset
   579
            self._abort(error.OutOfBandError(hint=msg))
36608
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   580
        if self._autoreadstderr:
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   581
            self._readerr()
646
342927da4f4c Show remote client output with "remote:"
Matt Mackall <mpm@selenic.com>
parents: 644
diff changeset
   582
        try:
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   583
            return int(l)
14004
97ed99d1f419 eliminate various naked except clauses
Idan Kamara <idankk86@gmail.com>
parents: 13827
diff changeset
   584
        except ValueError:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   585
            self._abort(error.ResponseError(_(b"unexpected response:"), l))
28438
48fd02dac1d4 wireproto: make iterbatcher behave streamily over http(s)
Augie Fackler <augie@google.com>
parents: 27798
diff changeset
   586
36363
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36216
diff changeset
   587
    def _readframed(self):
36628
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36608
diff changeset
   588
        size = self._getamount()
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36608
diff changeset
   589
        if not size:
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36608
diff changeset
   590
            return b''
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36608
diff changeset
   591
70415568ea65 sshpeer: don't read(0)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36608
diff changeset
   592
        return self._pipei.read(size)
5978
7939c71f3132 sshrepo: be more careful while reading data
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 5293
diff changeset
   593
36363
7f8f74531b0b sshpeer: rename _recv and _send to _readframed and _writeframed
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36216
diff changeset
   594
    def _writeframed(self, data, flush=False):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   595
        self._pipeo.write(b"%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
   596
        if data:
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   597
            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
   598
        if flush:
33768
82d564d5ac4f sshpeer: make instance attributes and methods internal
Gregory Szorc <gregory.szorc@gmail.com>
parents: 33737
diff changeset
   599
            self._pipeo.flush()
36608
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   600
        if self._autoreadstderr:
1151c731686e sshpeer: don't read from stderr when that behavior is disabled
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36536
diff changeset
   601
            self._readerr()
2612
ffb895f16925 add support for streaming clone.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2549
diff changeset
   602
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   603
35978
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   604
class sshv2peer(sshv1peer):
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   605
    """A peer that speakers version 2 of the transport protocol."""
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   606
35978
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   607
    # Currently version 2 is identical to version 1 post handshake.
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   608
    # And handshake is performed before the peer is instantiated. So
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   609
    # we need no custom code.
59e4a7781a36 sshpeer: implement peer for version 2 of wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35977
diff changeset
   610
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   611
36533
1a36ef7df70a sshpeer: support not reading and forwarding stderr
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36487
diff changeset
   612
def makepeer(ui, path, proc, stdin, stdout, stderr, autoreadstderr=True):
36487
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   613
    """Make a peer instance from existing pipes.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   614
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   615
    ``path`` and ``proc`` are stored on the eventual peer instance and may
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   616
    not be used for anything meaningful.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   617
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   618
    ``stdin``, ``stdout``, and ``stderr`` are the pipes connected to the
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   619
    SSH server's stdio handles.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   620
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   621
    This function is factored out to allow creating peers that don't
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   622
    actually spawn a new process. It is useful for starting SSH protocol
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   623
    servers and clients via non-standard means, which can be useful for
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   624
    testing.
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   625
    """
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   626
    try:
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   627
        protoname, caps = _performhandshake(ui, stdin, stdout, stderr)
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   628
    except Exception:
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   629
        _cleanuppipes(ui, stdout, stdin, stderr, warn=None)
36487
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   630
        raise
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   631
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36533
diff changeset
   632
    if protoname == wireprototypes.SSHV1:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   633
        return sshv1peer(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   634
            ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   635
            path,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   636
            proc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   637
            stdin,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   638
            stdout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   639
            stderr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   640
            caps,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   641
            autoreadstderr=autoreadstderr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   642
        )
36536
3cd245945ef3 wireprotoserver: move SSHV1 and SSHV2 constants to wireprototypes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36533
diff changeset
   643
    elif protoname == wireprototypes.SSHV2:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   644
        return sshv2peer(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   645
            ui,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   646
            path,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   647
            proc,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   648
            stdin,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   649
            stdout,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   650
            stderr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   651
            caps,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   652
            autoreadstderr=autoreadstderr,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   653
        )
36487
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   654
    else:
46662
db8037e38085 sshpeer: add a develwarning if an sshpeer is not closed explicitly
Valentin Gatien-Baron <valentin.gatienbaron@gmail.com>
parents: 46660
diff changeset
   655
        _cleanuppipes(ui, stdout, stdin, stderr, warn=None)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   656
        raise error.RepoError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   657
            _(b'unknown version of SSH protocol: %s') % protoname
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   658
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   659
36487
dabf86721200 sshpeer: factor out code for creating peers from pipes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36372
diff changeset
   660
39549
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   661
def instance(ui, path, create, intents=None, createopts=None):
35931
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   662
    """Create an SSH peer.
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   663
37614
a81d02ea65db wireproto: move version 1 peer functionality to standalone module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37498
diff changeset
   664
    The returned object conforms to the ``wireprotov1peer.wirepeer`` interface.
35931
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   665
    """
46907
ffd3e823a7e5 urlutil: extract `url` related code from `util` into the new module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
   666
    u = urlutil.url(path, parsequery=False, parsefragment=False)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   667
    if u.scheme != b'ssh' or not u.host or u.path is None:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   668
        raise error.RepoError(_(b"couldn't parse location %s") % path)
35931
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   669
46907
ffd3e823a7e5 urlutil: extract `url` related code from `util` into the new module
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 46819
diff changeset
   670
    urlutil.checksafessh(path)
35931
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   671
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   672
    if u.passwd is not None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   673
        raise error.RepoError(_(b'password in URL not supported'))
35931
b202d360d2a4 sshpeer: move URL validation out of sshpeer.__init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35928
diff changeset
   674
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   675
    sshcmd = ui.config(b'ui', b'ssh')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   676
    remotecmd = ui.config(b'ui', b'remotecmd')
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   677
    sshaddenv = dict(ui.configitems(b'sshenv'))
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
   678
    sshenv = procutil.shellenviron(sshaddenv)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   679
    remotepath = u.path or b'.'
35932
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   680
37120
a8a902d7176e procutil: bulk-replace function calls to point to new module
Yuya Nishihara <yuya@tcha.org>
parents: 36833
diff changeset
   681
    args = procutil.sshargs(sshcmd, u.host, u.user, u.port)
35932
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   682
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   683
    if create:
39549
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   684
        # We /could/ do this, but only if the remote init command knows how to
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   685
        # handle them. We don't yet make any assumptions about that. And without
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   686
        # querying the remote, there's no way of knowing if the remote even
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   687
        # supports said requested feature.
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   688
        if createopts:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   689
            raise error.RepoError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   690
                _(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   691
                    b'cannot create remote SSH repositories '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   692
                    b'with extra options'
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   693
                )
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   694
            )
39549
089fc0db0954 hg: allow extra arguments to be passed to repo creation (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 38713
diff changeset
   695
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   696
        cmd = b'%s %s %s' % (
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   697
            sshcmd,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   698
            args,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   699
            procutil.shellquote(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   700
                b'%s init %s'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   701
                % (_serverquote(remotecmd), _serverquote(remotepath))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   702
            ),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   703
        )
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   704
        ui.debug(b'running %s\n' % cmd)
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   705
        res = ui.system(cmd, blockedtag=b'sshpeer', environ=sshenv)
35932
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   706
        if res != 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   707
            raise error.RepoError(_(b'could not create remote repo'))
35932
31449baf0936 sshpeer: move ssh command and repo creation logic out of __init__
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35931
diff changeset
   708
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   709
    proc, stdin, stdout, stderr = _makeconnection(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   710
        ui, sshcmd, args, remotecmd, remotepath, sshenv
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   711
    )
35935
00b9e26d727b sshpeer: establish SSH connection before class instantiation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35934
diff changeset
   712
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   713
    peer = makepeer(ui, path, proc, stdin, stdout, stderr)
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   714
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   715
    # Finally, if supported by the server, notify it about our own
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   716
    # capabilities.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   717
    if b'protocaps' in peer.capabilities():
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   718
        try:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   719
            peer._call(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   720
                b"protocaps", caps=b' '.join(sorted(_clientcapabilities()))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 39549
diff changeset
   721
            )
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   722
        except IOError:
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   723
            peer._cleanup()
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   724
            raise error.RepoError(_(b'capability exchange failed'))
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   725
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37321
diff changeset
   726
    return peer