mercurial/wireprotov2peer.py
author Yuya Nishihara <yuya@tcha.org>
Mon, 07 Dec 2020 20:12:36 +0900
changeset 46065 56a5ea353182
parent 43506 9f70512ae2cf
permissions -rw-r--r--
test-extension: flush diagnostic message to stabilize chg output Since chg server may create new file object for the attached stdout, procutil.stdout is not ui.fout and the buffered procutil.stdout data wouldn't be flushed at all. That's why test-extension.t passes without modification on Python 2.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     1
# wireprotov2peer.py - client side code for wire protocol version 2
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     2
#
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     3
# Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     4
#
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     5
# This software may be used and distributed according to the terms of the
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     6
# GNU General Public License version 2 or any later version.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     7
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     8
from __future__ import absolute_import
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     9
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
    10
import threading
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
    11
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    12
from .i18n import _
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    13
from . import (
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
    14
    encoding,
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    15
    error,
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
    16
    pycompat,
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    17
    sslutil,
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
    18
    url as urlmod,
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
    19
    util,
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    20
    wireprotoframing,
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
    21
    wireprototypes,
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    22
)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    23
from .utils import cborutil
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    24
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    25
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    26
def formatrichmessage(atoms):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    27
    """Format an encoded message from the framing protocol."""
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    28
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    29
    chunks = []
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    30
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    31
    for atom in atoms:
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    32
        msg = _(atom[b'msg'])
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    33
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    34
        if b'args' in atom:
39486
43d92d68ac88 wireprotov2peer: properly format errors
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39485
diff changeset
    35
            msg = msg % tuple(atom[b'args'])
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    36
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    37
        chunks.append(msg)
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    38
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    39
    return b''.join(chunks)
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
    40
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    41
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    42
SUPPORTED_REDIRECT_PROTOCOLS = {
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    43
    b'http',
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    44
    b'https',
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    45
}
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    46
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    47
SUPPORTED_CONTENT_HASHES = {
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    48
    b'sha1',
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    49
    b'sha256',
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    50
}
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    51
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    52
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    53
def redirecttargetsupported(ui, target):
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    54
    """Determine whether a redirect target entry is supported.
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    55
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    56
    ``target`` should come from the capabilities data structure emitted by
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    57
    the server.
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    58
    """
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    59
    if target.get(b'protocol') not in SUPPORTED_REDIRECT_PROTOCOLS:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    60
        ui.note(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    61
            _(b'(remote redirect target %s uses unsupported protocol: %s)\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    62
            % (target[b'name'], target.get(b'protocol', b''))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    63
        )
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    64
        return False
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    65
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    66
    if target.get(b'snirequired') and not sslutil.hassni:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    67
        ui.note(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    68
            _(b'(redirect target %s requires SNI, which is unsupported)\n')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    69
            % target[b'name']
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    70
        )
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    71
        return False
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    72
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    73
    if b'tlsversions' in target:
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    74
        tlsversions = set(target[b'tlsversions'])
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    75
        supported = set()
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    76
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    77
        for v in sslutil.supportedprotocols:
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    78
            assert v.startswith(b'tls')
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    79
            supported.add(v[3:])
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    80
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    81
        if not tlsversions & supported:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    82
            ui.note(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    83
                _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    84
                    b'(remote redirect target %s requires unsupported TLS '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    85
                    b'versions: %s)\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    86
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    87
                % (target[b'name'], b', '.join(sorted(tlsversions)))
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    88
            )
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    89
            return False
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    90
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    91
    ui.note(_(b'(remote redirect target %s is compatible)\n') % target[b'name'])
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    92
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    93
    return True
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    94
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
    95
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    96
def supportedredirects(ui, apidescriptor):
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    97
    """Resolve the "redirect" command request key given an API descriptor.
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    98
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
    99
    Given an API descriptor returned by the server, returns a data structure
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   100
    that can be used in hte "redirect" field of command requests to advertise
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   101
    support for compatible redirect targets.
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   102
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   103
    Returns None if no redirect targets are remotely advertised or if none are
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   104
    supported.
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   105
    """
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   106
    if not apidescriptor or b'redirect' not in apidescriptor:
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   107
        return None
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   108
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   109
    targets = [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   110
        t[b'name']
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   111
        for t in apidescriptor[b'redirect'][b'targets']
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   112
        if redirecttargetsupported(ui, t)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   113
    ]
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   114
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   115
    hashes = [
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   116
        h
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   117
        for h in apidescriptor[b'redirect'][b'hashes']
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   118
        if h in SUPPORTED_CONTENT_HASHES
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   119
    ]
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   120
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   121
    return {
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   122
        b'targets': targets,
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   123
        b'hashes': hashes,
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   124
    }
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   125
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   126
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   127
class commandresponse(object):
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   128
    """Represents the response to a command request.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   129
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   130
    Instances track the state of the command and hold its results.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   131
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   132
    An external entity is required to update the state of the object when
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   133
    events occur.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   134
    """
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   135
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   136
    def __init__(self, requestid, command, fromredirect=False):
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   137
        self.requestid = requestid
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   138
        self.command = command
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   139
        self.fromredirect = fromredirect
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   140
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   141
        # Whether all remote input related to this command has been
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   142
        # received.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   143
        self._inputcomplete = False
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   144
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   145
        # We have a lock that is acquired when important object state is
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   146
        # mutated. This is to prevent race conditions between 1 thread
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   147
        # sending us new data and another consuming it.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   148
        self._lock = threading.RLock()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   149
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   150
        # An event is set when state of the object changes. This event
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   151
        # is waited on by the generator emitting objects.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   152
        self._serviceable = threading.Event()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   153
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   154
        self._pendingevents = []
40137
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   155
        self._pendingerror = None
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   156
        self._decoder = cborutil.bufferingdecoder()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   157
        self._seeninitial = False
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   158
        self._redirect = None
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   159
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   160
    def _oninputcomplete(self):
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   161
        with self._lock:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   162
            self._inputcomplete = True
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   163
            self._serviceable.set()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   164
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   165
    def _onresponsedata(self, data):
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   166
        available, readcount, wanted = self._decoder.decode(data)
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   167
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   168
        if not available:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   169
            return
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   170
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   171
        with self._lock:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   172
            for o in self._decoder.getavailable():
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   173
                if not self._seeninitial and not self.fromredirect:
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   174
                    self._handleinitial(o)
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   175
                    continue
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   176
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   177
                # We should never see an object after a content redirect,
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   178
                # as the spec says the main status object containing the
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   179
                # content redirect is the only object in the stream. Fail
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   180
                # if we see a misbehaving server.
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   181
                if self._redirect:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   182
                    raise error.Abort(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   183
                        _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   184
                            b'received unexpected response data '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   185
                            b'after content redirect; the remote is '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   186
                            b'buggy'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   187
                        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   188
                    )
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   189
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   190
                self._pendingevents.append(o)
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   191
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   192
            self._serviceable.set()
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   193
40137
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   194
    def _onerror(self, e):
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   195
        self._pendingerror = e
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   196
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   197
        with self._lock:
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   198
            self._serviceable.set()
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   199
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   200
    def _handleinitial(self, o):
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   201
        self._seeninitial = True
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   202
        if o[b'status'] == b'ok':
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   203
            return
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   204
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   205
        elif o[b'status'] == b'redirect':
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   206
            l = o[b'location']
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   207
            self._redirect = wireprototypes.alternatelocationresponse(
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   208
                url=l[b'url'],
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   209
                mediatype=l[b'mediatype'],
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   210
                size=l.get(b'size'),
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   211
                fullhashes=l.get(b'fullhashes'),
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   212
                fullhashseed=l.get(b'fullhashseed'),
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   213
                serverdercerts=l.get(b'serverdercerts'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   214
                servercadercerts=l.get(b'servercadercerts'),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   215
            )
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   216
            return
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   217
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   218
        atoms = [{b'msg': o[b'error'][b'message']}]
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   219
        if b'args' in o[b'error']:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   220
            atoms[0][b'args'] = o[b'error'][b'args']
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   221
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   222
        raise error.RepoError(formatrichmessage(atoms))
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   223
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   224
    def objects(self):
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   225
        """Obtained decoded objects from this response.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   226
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   227
        This is a generator of data structures that were decoded from the
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   228
        command response.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   229
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   230
        Obtaining the next member of the generator may block due to waiting
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   231
        on external data to become available.
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   232
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   233
        If the server encountered an error in the middle of serving the data
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   234
        or if another error occurred, an exception may be raised when
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   235
        advancing the generator.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   236
        """
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   237
        while True:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   238
            # TODO this can infinite loop if self._inputcomplete is never
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   239
            # set. We likely want to tie the lifetime of this object/state
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   240
            # to that of the background thread receiving frames and updating
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   241
            # our state.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   242
            self._serviceable.wait(1.0)
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   243
40137
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   244
            if self._pendingerror:
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   245
                raise self._pendingerror
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   246
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   247
            with self._lock:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   248
                self._serviceable.clear()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   249
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   250
                # Make copies because objects could be mutated during
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   251
                # iteration.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   252
                stop = self._inputcomplete
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   253
                pending = list(self._pendingevents)
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   254
                self._pendingevents[:] = []
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   255
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   256
            for o in pending:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   257
                yield o
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   258
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   259
            if stop:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   260
                break
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   261
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   262
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   263
class clienthandler(object):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   264
    """Object to handle higher-level client activities.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   265
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   266
    The ``clientreactor`` is used to hold low-level state about the frame-based
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   267
    protocol, such as which requests and streams are active. This type is used
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   268
    for higher-level operations, such as reading frames from a socket, exposing
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   269
    and managing a higher-level primitive for representing command responses,
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   270
    etc. This class is what peers should probably use to bridge wire activity
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   271
    with the higher-level peer API.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   272
    """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   273
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   274
    def __init__(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   275
        self, ui, clientreactor, opener=None, requestbuilder=util.urlreq.request
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   276
    ):
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   277
        self._ui = ui
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   278
        self._reactor = clientreactor
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   279
        self._requests = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   280
        self._futures = {}
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   281
        self._responses = {}
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   282
        self._redirects = []
40019
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   283
        self._frameseof = False
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   284
        self._opener = opener or urlmod.opener(ui)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   285
        self._requestbuilder = requestbuilder
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   286
40024
86b22a4cfab1 wireprotov2: client support for advertising redirect targets
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40019
diff changeset
   287
    def callcommand(self, command, args, f, redirect=None):
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   288
        """Register a request to call a command.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   289
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   290
        Returns an iterable of frames that should be sent over the wire.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   291
        """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   292
        request, action, meta = self._reactor.callcommand(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   293
            command, args, redirect=redirect
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   294
        )
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   295
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   296
        if action != b'noop':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   297
            raise error.ProgrammingError(b'%s not yet supported' % action)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   298
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   299
        rid = request.requestid
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   300
        self._requests[rid] = request
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   301
        self._futures[rid] = f
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   302
        # TODO we need some kind of lifetime on response instances otherwise
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   303
        # objects() may deadlock.
37720
d715a85003c8 wireprotov2: establish a type for representing command response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37719
diff changeset
   304
        self._responses[rid] = commandresponse(rid, command)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   305
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   306
        return iter(())
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   307
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   308
    def flushcommands(self):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   309
        """Flush all queued commands.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   310
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   311
        Returns an iterable of frames that should be sent over the wire.
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   312
        """
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   313
        action, meta = self._reactor.flushcommands()
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   314
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   315
        if action != b'sendframes':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   316
            raise error.ProgrammingError(b'%s not yet supported' % action)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   317
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   318
        return meta[b'framegen']
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   319
40019
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   320
    def readdata(self, framefh):
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   321
        """Attempt to read data and do work.
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   322
40019
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   323
        Returns None if no data was read. Presumably this means we're
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   324
        done with all read I/O.
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   325
        """
40019
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   326
        if not self._frameseof:
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   327
            frame = wireprotoframing.readframe(framefh)
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   328
            if frame is None:
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   329
                # TODO tell reactor?
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   330
                self._frameseof = True
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   331
            else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   332
                self._ui.debug(b'received %r\n' % frame)
40019
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   333
                self._processframe(frame)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   334
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   335
        # Also try to read the first redirect.
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   336
        if self._redirects:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   337
            if not self._processredirect(*self._redirects[0]):
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   338
                self._redirects.pop(0)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   339
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   340
        if self._frameseof and not self._redirects:
40019
f5a05bb48116 wireprotov2: change name and behavior of readframe()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39561
diff changeset
   341
            return None
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   342
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   343
        return True
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   344
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   345
    def _processframe(self, frame):
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   346
        """Process a single read frame."""
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   347
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   348
        action, meta = self._reactor.onframerecv(frame)
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   349
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   350
        if action == b'error':
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   351
            e = error.RepoError(meta[b'message'])
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   352
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   353
            if frame.requestid in self._responses:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   354
                self._responses[frame.requestid]._oninputcomplete()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   355
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   356
            if frame.requestid in self._futures:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   357
                self._futures[frame.requestid].set_exception(e)
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   358
                del self._futures[frame.requestid]
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   359
            else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   360
                raise e
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   361
39559
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39486
diff changeset
   362
            return
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   363
        elif action == b'noop':
40134
cfeba1aafb9d wireprotov2: handle noop action
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40026
diff changeset
   364
            return
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   365
        elif action == b'responsedata':
40139
17223d8e7d75 wireprotov2: raise ProgrammingError on unknown action
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40137
diff changeset
   366
            # Handled below.
17223d8e7d75 wireprotov2: raise ProgrammingError on unknown action
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40137
diff changeset
   367
            pass
17223d8e7d75 wireprotov2: raise ProgrammingError on unknown action
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40137
diff changeset
   368
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   369
            raise error.ProgrammingError(b'action not handled: %s' % action)
39559
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39486
diff changeset
   370
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   371
        if frame.requestid not in self._requests:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   372
            raise error.ProgrammingError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   373
                b'received frame for unknown request; this is either a bug in '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   374
                b'the clientreactor not screening for this or this instance was '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   375
                b'never told about this request: %r' % frame
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   376
            )
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   377
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   378
        response = self._responses[frame.requestid]
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   379
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   380
        if action == b'responsedata':
39485
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
   381
            # Any failures processing this frame should bubble up to the
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
   382
            # future tracking the request.
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
   383
            try:
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
   384
                self._processresponsedata(frame, meta, response)
42bc1c70a6b8 wireprotov2peer: report exceptions in frame handling against request future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39450
diff changeset
   385
            except BaseException as e:
40137
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   386
                # If an exception occurs before the future is resolved,
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   387
                # fail the future. Otherwise, we stuff the exception on
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   388
                # the response object so it can be raised during objects()
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   389
                # iteration. If nothing is consuming objects(), we could
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   390
                # silently swallow this exception. That's a risk we'll have to
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   391
                # take.
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   392
                if frame.requestid in self._futures:
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   393
                    self._futures[frame.requestid].set_exception(e)
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   394
                    del self._futures[frame.requestid]
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   395
                    response._oninputcomplete()
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   396
                else:
ed4ebbb98ca0 wireprotov2: raise exception in objects() if future has been resolved
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40134
diff changeset
   397
                    response._onerror(e)
37719
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   398
        else:
a656cba08a04 wireprotov2: move response handling out of httppeer
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   399
            raise error.ProgrammingError(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   400
                b'unhandled action from clientreactor: %s' % action
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   401
            )
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   402
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
   403
    def _processresponsedata(self, frame, meta, response):
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   404
        # This can raise. The caller can handle it.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   405
        response._onresponsedata(meta[b'data'])
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
   406
40724
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   407
        # We need to be careful about resolving futures prematurely. If a
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   408
        # response is a redirect response, resolving the future before the
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   409
        # redirect is processed would result in the consumer seeing an
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   410
        # empty stream of objects, since they'd be consuming our
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   411
        # response.objects() instead of the redirect's response.objects().
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   412
        #
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   413
        # Our strategy is to not resolve/finish the request until either
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   414
        # EOS occurs or until the initial response object is fully received.
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   415
40724
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   416
        # Always react to eos.
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   417
        if meta[b'eos']:
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   418
            response._oninputcomplete()
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   419
            del self._requests[frame.requestid]
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
   420
40724
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   421
        # Not EOS but we haven't decoded the initial response object yet.
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   422
        # Return and wait for more data.
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   423
        elif not response._seeninitial:
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   424
            return
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   425
40724
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   426
        # The specification says no objects should follow the initial/redirect
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   427
        # object. So it should be safe to handle the redirect object if one is
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   428
        # decoded, without having to wait for EOS.
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   429
        if response._redirect:
15a643304728 wireprotov2peer: wait for initial object before resolving future
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40723
diff changeset
   430
            self._followredirect(frame.requestid, response._redirect)
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   431
            return
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   432
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   433
        # If the command has a decoder, we wait until all input has been
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   434
        # received before resolving the future. Otherwise we resolve the
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   435
        # future immediately.
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   436
        if frame.requestid not in self._futures:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   437
            return
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
   438
39561
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   439
        if response.command not in COMMAND_DECODERS:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   440
            self._futures[frame.requestid].set_result(response.objects())
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   441
            del self._futures[frame.requestid]
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   442
        elif response._inputcomplete:
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   443
            decoded = COMMAND_DECODERS[response.command](response.objects())
d06834e0f48e wireprotov2peer: stream decoded responses
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39559
diff changeset
   444
            self._futures[frame.requestid].set_result(decoded)
39438
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
   445
            del self._futures[frame.requestid]
c734a5c82f38 wireprotov2peer: split responsedata handling into separate function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39435
diff changeset
   446
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   447
    def _followredirect(self, requestid, redirect):
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   448
        """Called to initiate redirect following for a request."""
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   449
        self._ui.note(_(b'(following redirect to %s)\n') % redirect.url)
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   450
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   451
        # TODO handle framed responses.
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   452
        if redirect.mediatype != b'application/mercurial-cbor':
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   453
            raise error.Abort(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   454
                _(b'cannot handle redirects for the %s media type')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   455
                % redirect.mediatype
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   456
            )
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   457
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   458
        if redirect.fullhashes:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   459
            self._ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   460
                _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   461
                    b'(support for validating hashes on content '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   462
                    b'redirects not supported)\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   463
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   464
            )
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   465
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   466
        if redirect.serverdercerts or redirect.servercadercerts:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   467
            self._ui.warn(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   468
                _(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   469
                    b'(support for pinning server certificates on '
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   470
                    b'content redirects not supported)\n'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   471
                )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   472
            )
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   473
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   474
        headers = {
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43077
diff changeset
   475
            'Accept': redirect.mediatype,
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   476
        }
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   477
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   478
        req = self._requestbuilder(pycompat.strurl(redirect.url), None, headers)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   479
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   480
        try:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   481
            res = self._opener.open(req)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   482
        except util.urlerr.httperror as e:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   483
            if e.code == 401:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   484
                raise error.Abort(_(b'authorization failed'))
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   485
            raise
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   486
        except util.httplib.HTTPException as e:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   487
            self._ui.debug(b'http error requesting %s\n' % req.get_full_url())
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   488
            self._ui.traceback()
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   489
            raise IOError(None, e)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   490
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   491
        urlmod.wrapresponse(res)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   492
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   493
        # The existing response object is associated with frame data. Rather
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   494
        # than try to normalize its state, just create a new object.
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   495
        oldresponse = self._responses[requestid]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   496
        self._responses[requestid] = commandresponse(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   497
            requestid, oldresponse.command, fromredirect=True
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   498
        )
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   499
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   500
        self._redirects.append((requestid, res))
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   501
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   502
    def _processredirect(self, rid, res):
40723
94b0d0f996e1 wireprotov2peer: always return a bool from _processredirect()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40139
diff changeset
   503
        """Called to continue processing a response from a redirect.
94b0d0f996e1 wireprotov2peer: always return a bool from _processredirect()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40139
diff changeset
   504
94b0d0f996e1 wireprotov2peer: always return a bool from _processredirect()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40139
diff changeset
   505
        Returns a bool indicating if the redirect is still serviceable.
94b0d0f996e1 wireprotov2peer: always return a bool from _processredirect()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40139
diff changeset
   506
        """
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   507
        response = self._responses[rid]
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   508
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   509
        try:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   510
            data = res.read(32768)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   511
            response._onresponsedata(data)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   512
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   513
            # We're at end of stream.
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   514
            if not data:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   515
                response._oninputcomplete()
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   516
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   517
            if rid not in self._futures:
40723
94b0d0f996e1 wireprotov2peer: always return a bool from _processredirect()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40139
diff changeset
   518
                return bool(data)
40026
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   519
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   520
            if response.command not in COMMAND_DECODERS:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   521
                self._futures[rid].set_result(response.objects())
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   522
                del self._futures[rid]
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   523
            elif response._inputcomplete:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   524
                decoded = COMMAND_DECODERS[response.command](response.objects())
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   525
                self._futures[rid].set_result(decoded)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   526
                del self._futures[rid]
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   527
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   528
            return bool(data)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   529
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   530
        except BaseException as e:
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   531
            self._futures[rid].set_exception(e)
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   532
            del self._futures[rid]
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   533
            response._oninputcomplete()
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   534
            return False
7e807b8a9e56 wireprotov2: client support for following content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   535
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   536
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   537
def decodebranchmap(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   538
    # Response should be a single CBOR map of branch name to array of nodes.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   539
    bm = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   540
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   541
    return {encoding.tolocal(k): v for k, v in bm.items()}
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   542
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   543
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   544
def decodeheads(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   545
    # Array of node bytestrings.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   546
    return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   547
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   548
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   549
def decodeknown(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   550
    # Bytestring where each byte is a 0 or 1.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   551
    raw = next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   552
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   553
    return [True if raw[i : i + 1] == b'1' else False for i in range(len(raw))]
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   554
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   555
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   556
def decodelistkeys(objs):
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   557
    # Map with bytestring keys and values.
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   558
    return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   559
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   560
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   561
def decodelookup(objs):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   562
    return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   563
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   564
37725
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   565
def decodepushkey(objs):
3ea8323d6f95 wireprotov2: change command response protocol to include a leading map
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37722
diff changeset
   566
    return next(objs)
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   567
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41380
diff changeset
   568
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   569
COMMAND_DECODERS = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   570
    b'branchmap': decodebranchmap,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   571
    b'heads': decodeheads,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   572
    b'known': decodeknown,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   573
    b'listkeys': decodelistkeys,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   574
    b'lookup': decodelookup,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   575
    b'pushkey': decodepushkey,
37721
f7673845b167 wireprotov2: decode responses to their expected types
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37720
diff changeset
   576
}