mercurial/wireprotov2server.py
author Augie Fackler <augie@google.com>
Mon, 07 Jan 2019 19:03:23 -0500
changeset 41130 074c72a38423
parent 40942 08cfa77d7288
child 41216 5cc5a5561c3f
permissions -rw-r--r--
merge with stable
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     1
# Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     2
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     3
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 8109
diff changeset
     4
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9713
diff changeset
     5
# GNU General Public License version 2 or any later version.
5598
d534ba1c4eb4 separate the wire protocol commands from the user interface commands
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents:
diff changeset
     6
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
     7
from __future__ import absolute_import
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
     8
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
     9
import collections
36104
2ad145fbde54 wireprotoserver: add context manager mechanism for redirecting stdio
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36103
diff changeset
    10
import contextlib
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    11
import hashlib
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
    12
35899
1bf5263fe5cc wireprotoserver: move sshserver into module (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35898
diff changeset
    13
from .i18n import _
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
    14
from .node import (
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
    15
    hex,
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
    16
    nullid,
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
    17
)
35896
ef3a24a023ec wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35750
diff changeset
    18
from . import (
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
    19
    discovery,
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
    20
    encoding,
34509
e21f274cccea hgweb: in protocol adapter, avoid control reaching end of non-void function
Augie Fackler <augie@google.com>
parents: 33842
diff changeset
    21
    error,
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
    22
    match as matchmod,
39816
ae20f52437e9 wireprotov2: advertise recognized path filter prefixes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39815
diff changeset
    23
    narrowspec,
34742
5a9cad0dfddb hgweb: when unpacking args from request form, convert to bytes
Augie Fackler <augie@google.com>
parents: 34740
diff changeset
    24
    pycompat,
40329
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
    25
    streamclone,
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
    26
    util,
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
    27
    wireprotoframing,
36111
cd6ab329c5c7 wireprototypes: move wire protocol response types to new module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36110
diff changeset
    28
    wireprototypes,
27046
37fcfe52c68c hgweb: use absolute_import
Yuya Nishihara <yuya@tcha.org>
parents: 20903
diff changeset
    29
)
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37784
diff changeset
    30
from .utils import (
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    31
    cborutil,
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37784
diff changeset
    32
    interfaceutil,
39842
69b4a5b89dc5 py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39833
diff changeset
    33
    stringutil,
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37784
diff changeset
    34
)
35896
ef3a24a023ec wireprotoserver: rename hgweb.protocol to wireprotoserver (API)
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35750
diff changeset
    35
40133
762ef19a07e3 wireprotov2: send protocol settings frame from client
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40130
diff changeset
    36
FRAMINGTYPE = b'application/mercurial-exp-framing-0006'
11595
368cd5325348 protocol: move hgweb protocol support back into protocol.py
Matt Mackall <mpm@selenic.com>
parents: 11594
diff changeset
    37
37644
77c9ee77687c wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37557
diff changeset
    38
HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2
36015
48a3a9283f09 sshpeer: initial definition and implementation of new SSH protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35940
diff changeset
    39
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
    40
COMMANDS = wireprototypes.commanddict()
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
    41
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    42
# Value inserted into cache key computation function. Change the value to
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    43
# force new cache keys for every command request. This should be done when
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    44
# there is a change to how caching works, etc.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    45
GLOBAL_CACHE_VERSION = 1
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
    46
37545
93397c4633f6 wireproto: extract HTTP version 2 code to own module
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37535
diff changeset
    47
def handlehttpv2request(rctx, req, res, checkperm, urlparts):
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    48
    from .hgweb import common as hgwebcommon
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    49
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    50
    # URL space looks like: <permissions>/<command>, where <permission> can
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    51
    # be ``ro`` or ``rw`` to signal read-only or read-write, respectively.
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    52
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    53
    # Root URL does nothing meaningful... yet.
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    54
    if not urlparts:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    55
        res.status = b'200 OK'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    56
        res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    57
        res.setbodybytes(_('HTTP version 2 API handler'))
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    58
        return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    59
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    60
    if len(urlparts) == 1:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    61
        res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    62
        res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    63
        res.setbodybytes(_('do not know how to process %s\n') %
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    64
                         req.dispatchpath)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    65
        return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    66
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    67
    permission, command = urlparts[0:2]
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    68
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    69
    if permission not in (b'ro', b'rw'):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    70
        res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    71
        res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    72
        res.setbodybytes(_('unknown permission: %s') % permission)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    73
        return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    74
37051
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
    75
    if req.method != 'POST':
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
    76
        res.status = b'405 Method Not Allowed'
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
    77
        res.headers[b'Allow'] = b'POST'
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
    78
        res.setbodybytes(_('commands require POST requests'))
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
    79
        return
fc5e261915b9 wireproto: require POST for all HTTPv2 requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37050
diff changeset
    80
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    81
    # At some point we'll want to use our own API instead of recycling the
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    82
    # behavior of version 1 of the wire protocol...
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    83
    # TODO return reasonable responses - not responses that overload the
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    84
    # HTTP status line message for error reporting.
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    85
    try:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    86
        checkperm(rctx, req, 'pull' if permission == b'ro' else 'push')
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    87
    except hgwebcommon.ErrorResponse as e:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    88
        res.status = hgwebcommon.statusmessage(e.code, pycompat.bytestr(e))
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    89
        for k, v in e.headers:
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    90
            res.headers[k] = v
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    91
        res.setbodybytes('permission denied')
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    92
        return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
    93
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
    94
    # We have a special endpoint to reflect the request back at the client.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
    95
    if command == b'debugreflect':
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
    96
        _processhttpv2reflectrequest(rctx.repo.ui, rctx.repo, req, res)
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
    97
        return
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
    98
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
    99
    # Extra commands that we handle that aren't really wire protocol
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   100
    # commands. Think extra hard before making this hackery available to
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   101
    # extension.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   102
    extracommands = {'multirequest'}
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   103
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   104
    if command not in COMMANDS and command not in extracommands:
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   105
        res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   106
        res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   107
        res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   108
        return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   109
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   110
    repo = rctx.repo
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   111
    ui = repo.ui
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   112
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   113
    proto = httpv2protocolhandler(req, ui)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   114
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   115
    if (not COMMANDS.commandavailable(command, proto)
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   116
        and command not in extracommands):
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   117
        res.status = b'404 Not Found'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   118
        res.headers[b'Content-Type'] = b'text/plain'
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   119
        res.setbodybytes(_('invalid wire protocol command: %s') % command)
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   120
        return
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   121
37132
aaabd709df72 wireproto: review fixups
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
   122
    # TODO consider cases where proxies may add additional Accept headers.
37054
40206e227412 wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
   123
    if req.headers.get(b'Accept') != FRAMINGTYPE:
37053
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   124
        res.status = b'406 Not Acceptable'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   125
        res.headers[b'Content-Type'] = b'text/plain'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   126
        res.setbodybytes(_('client MUST specify Accept header with value: %s\n')
37054
40206e227412 wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
   127
                           % FRAMINGTYPE)
37053
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   128
        return
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   129
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   130
    if req.headers.get(b'Content-Type') != FRAMINGTYPE:
37053
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   131
        res.status = b'415 Unsupported Media Type'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   132
        # TODO we should send a response with appropriate media type,
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   133
        # since client does Accept it.
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   134
        res.headers[b'Content-Type'] = b'text/plain'
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   135
        res.setbodybytes(_('client MUST send Content-Type header with '
37054
40206e227412 wireproto: define and implement protocol for issuing requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37053
diff changeset
   136
                           'value: %s\n') % FRAMINGTYPE)
37053
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   137
        return
37d7a1d18b97 wireproto: define content negotiation for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37051
diff changeset
   138
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   139
    _processhttpv2request(ui, repo, req, res, permission, command, proto)
37049
1cfef5693203 wireproto: support /api/* URL space for exposing APIs
Gregory Szorc <gregory.szorc@gmail.com>
parents: 36883
diff changeset
   140
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   141
def _processhttpv2reflectrequest(ui, repo, req, res):
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   142
    """Reads unified frame protocol request and dumps out state to client.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   143
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   144
    This special endpoint can be used to help debug the wire protocol.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   145
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   146
    Instead of routing the request through the normal dispatch mechanism,
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   147
    we instead read all frames, decode them, and feed them into our state
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   148
    tracker. We then dump the log of all that activity back out to the
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   149
    client.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   150
    """
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   151
    import json
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   152
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   153
    # Reflection APIs have a history of being abused, accidentally disclosing
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   154
    # sensitive data, etc. So we have a config knob.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   155
    if not ui.configbool('experimental', 'web.api.debugreflect'):
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   156
        res.status = b'404 Not Found'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   157
        res.headers[b'Content-Type'] = b'text/plain'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   158
        res.setbodybytes(_('debugreflect service not available'))
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   159
        return
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   160
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   161
    # We assume we have a unified framing protocol request body.
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   162
40130
293835e0fff7 wireprotov2: pass ui into clientreactor and serverreactor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40123
diff changeset
   163
    reactor = wireprotoframing.serverreactor(ui)
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   164
    states = []
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   165
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   166
    while True:
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   167
        frame = wireprotoframing.readframe(req.bodyfh)
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   168
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   169
        if not frame:
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   170
            states.append(b'received: <no frame>')
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   171
            break
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   172
37064
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37062
diff changeset
   173
        states.append(b'received: %d %d %d %s' % (frame.typeid, frame.flags,
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37062
diff changeset
   174
                                                  frame.requestid,
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37062
diff changeset
   175
                                                  frame.payload))
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   176
37064
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37062
diff changeset
   177
        action, meta = reactor.onframerecv(frame)
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   178
        states.append(json.dumps((action, meta), sort_keys=True,
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   179
                                 separators=(', ', ': ')))
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   180
37059
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   181
    action, meta = reactor.oninputeof()
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   182
    meta['action'] = action
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   183
    states.append(json.dumps(meta, sort_keys=True, separators=(', ',': ')))
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   184
37055
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   185
    res.status = b'200 OK'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   186
    res.headers[b'Content-Type'] = b'text/plain'
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   187
    res.setbodybytes(b'\n'.join(states))
8c3c47362934 wireproto: implement basic frame reading and processing
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37054
diff changeset
   188
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   189
def _processhttpv2request(ui, repo, req, res, authedperm, reqcommand, proto):
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   190
    """Post-validation handler for HTTPv2 requests.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   191
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   192
    Called when the HTTP request contains unified frame-based protocol
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   193
    frames for evaluation.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   194
    """
37059
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   195
    # TODO Some HTTP clients are full duplex and can receive data before
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   196
    # the entire request is transmitted. Figure out a way to indicate support
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   197
    # for that so we can opt into full duplex mode.
40130
293835e0fff7 wireprotov2: pass ui into clientreactor and serverreactor
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40123
diff changeset
   198
    reactor = wireprotoframing.serverreactor(ui, deferoutput=True)
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   199
    seencommand = False
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   200
40138
b5bf3dd6ec5b wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40133
diff changeset
   201
    outstream = None
37289
5fadc63ac99f wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37288
diff changeset
   202
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   203
    while True:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   204
        frame = wireprotoframing.readframe(req.bodyfh)
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   205
        if not frame:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   206
            break
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   207
37064
884a0c1604ad wireproto: define attr-based classes for representing frames
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37062
diff changeset
   208
        action, meta = reactor.onframerecv(frame)
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   209
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   210
        if action == 'wantframe':
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   211
            # Need more data before we can do anything.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   212
            continue
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   213
        elif action == 'runcommand':
40138
b5bf3dd6ec5b wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40133
diff changeset
   214
            # Defer creating output stream because we need to wait for
b5bf3dd6ec5b wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40133
diff changeset
   215
            # protocol settings frames so proper encoding can be applied.
b5bf3dd6ec5b wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40133
diff changeset
   216
            if not outstream:
b5bf3dd6ec5b wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40133
diff changeset
   217
                outstream = reactor.makeoutputstream()
b5bf3dd6ec5b wireprotov2: send content encoded frames from server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40133
diff changeset
   218
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   219
            sentoutput = _httpv2runcommand(ui, repo, req, res, authedperm,
37289
5fadc63ac99f wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37288
diff changeset
   220
                                           reqcommand, reactor, outstream,
5fadc63ac99f wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37288
diff changeset
   221
                                           meta, issubsequent=seencommand)
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   222
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   223
            if sentoutput:
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   224
                return
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   225
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   226
            seencommand = True
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   227
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   228
        elif action == 'error':
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   229
            # TODO define proper error mechanism.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   230
            res.status = b'200 OK'
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   231
            res.headers[b'Content-Type'] = b'text/plain'
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   232
            res.setbodybytes(meta['message'] + b'\n')
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   233
            return
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   234
        else:
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   235
            raise error.ProgrammingError(
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   236
                'unhandled action from frame processor: %s' % action)
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   237
37059
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   238
    action, meta = reactor.oninputeof()
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   239
    if action == 'sendframes':
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   240
        # We assume we haven't started sending the response yet. If we're
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   241
        # wrong, the response type will raise an exception.
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   242
        res.status = b'200 OK'
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   243
        res.headers[b'Content-Type'] = FRAMINGTYPE
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   244
        res.setbodygen(meta['framegen'])
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   245
    elif action == 'noop':
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   246
        pass
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   247
    else:
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   248
        raise error.ProgrammingError('unhandled action from frame processor: %s'
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   249
                                     % action)
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   250
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   251
def _httpv2runcommand(ui, repo, req, res, authedperm, reqcommand, reactor,
37289
5fadc63ac99f wireproto: explicit API to create outgoing streams
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37288
diff changeset
   252
                      outstream, command, issubsequent):
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   253
    """Dispatch a wire protocol command made from HTTPv2 requests.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   254
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   255
    The authenticated permission (``authedperm``) along with the original
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   256
    command from the URL (``reqcommand``) are passed in.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   257
    """
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   258
    # We already validated that the session has permissions to perform the
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   259
    # actions in ``authedperm``. In the unified frame protocol, the canonical
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   260
    # command to run is expressed in a frame. However, the URL also requested
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   261
    # to run a specific command. We need to be careful that the command we
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   262
    # run doesn't have permissions requirements greater than what was granted
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   263
    # by ``authedperm``.
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   264
    #
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   265
    # Our rule for this is we only allow one command per HTTP request and
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   266
    # that command must match the command in the URL. However, we make
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   267
    # an exception for the ``multirequest`` URL. This URL is allowed to
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   268
    # execute multiple commands. We double check permissions of each command
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   269
    # as it is invoked to ensure there is no privilege escalation.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   270
    # TODO consider allowing multiple commands to regular command URLs
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   271
    # iff each command is the same.
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   272
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   273
    proto = httpv2protocolhandler(req, ui, args=command['args'])
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   274
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   275
    if reqcommand == b'multirequest':
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   276
        if not COMMANDS.commandavailable(command['command'], proto):
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   277
            # TODO proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   278
            res.status = b'200 OK'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   279
            res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   280
            res.setbodybytes(_('wire protocol command not available: %s') %
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   281
                             command['command'])
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   282
            return True
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   283
37132
aaabd709df72 wireproto: review fixups
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
   284
        # TODO don't use assert here, since it may be elided by -O.
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   285
        assert authedperm in (b'ro', b'rw')
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   286
        wirecommand = COMMANDS[command['command']]
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   287
        assert wirecommand.permission in ('push', 'pull')
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   288
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   289
        if authedperm == b'ro' and wirecommand.permission != 'pull':
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   290
            # TODO proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   291
            res.status = b'403 Forbidden'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   292
            res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   293
            res.setbodybytes(_('insufficient permissions to execute '
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   294
                               'command: %s') % command['command'])
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   295
            return True
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   296
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   297
        # TODO should we also call checkperm() here? Maybe not if we're going
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   298
        # to overhaul that API. The granted scope from the URL check should
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   299
        # be good enough.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   300
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   301
    else:
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   302
        # Don't allow multiple commands outside of ``multirequest`` URL.
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   303
        if issubsequent:
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   304
            # TODO proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   305
            res.status = b'200 OK'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   306
            res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   307
            res.setbodybytes(_('multiple commands cannot be issued to this '
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   308
                               'URL'))
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   309
            return True
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   310
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   311
        if reqcommand != command['command']:
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   312
            # TODO define proper error mechanism
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   313
            res.status = b'200 OK'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   314
            res.headers[b'Content-Type'] = b'text/plain'
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   315
            res.setbodybytes(_('command in frame must match command in URL'))
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   316
            return True
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   317
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   318
    res.status = b'200 OK'
37058
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   319
    res.headers[b'Content-Type'] = FRAMINGTYPE
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   320
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   321
    try:
40026
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   322
        objs = dispatch(repo, proto, command['command'], command['redirect'])
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   323
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   324
        action, meta = reactor.oncommandresponsereadyobjects(
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   325
            outstream, command['requestid'], objs)
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   326
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   327
    except error.WireprotoCommandError as e:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   328
        action, meta = reactor.oncommanderror(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   329
            outstream, command['requestid'], e.message, e.messageargs)
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   330
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   331
    except Exception as e:
37726
0c184ca594bb wireprotov2: change behavior of error frame
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37725
diff changeset
   332
        action, meta = reactor.onservererror(
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   333
            outstream, command['requestid'],
39842
69b4a5b89dc5 py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39833
diff changeset
   334
            _('exception when invoking command: %s') %
69b4a5b89dc5 py3: cast exception to bytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39833
diff changeset
   335
            stringutil.forcebytestr(e))
37058
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   336
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   337
    if action == 'sendframes':
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   338
        res.setbodygen(meta['framegen'])
37062
bbea991635d0 wireproto: service multiple command requests per HTTP request
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37060
diff changeset
   339
        return True
37059
861e9d37e56e wireproto: buffer output frames when in half duplex mode
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37058
diff changeset
   340
    elif action == 'noop':
37132
aaabd709df72 wireproto: review fixups
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37123
diff changeset
   341
        return False
37058
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   342
    else:
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   343
        raise error.ProgrammingError('unhandled event from reactor: %s' %
61393f888dfe wireproto: define and implement responses in framing protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37057
diff changeset
   344
                                     action)
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   345
37782
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   346
def getdispatchrepo(repo, proto, command):
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   347
    return repo.filtered('served')
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   348
40026
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   349
def dispatch(repo, proto, command, redirect):
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   350
    """Run a wire protocol command.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   351
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   352
    Returns an iterable of objects that will be sent to the client.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   353
    """
37782
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   354
    repo = getdispatchrepo(repo, proto, command)
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   355
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   356
    entry = COMMANDS[command]
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   357
    func = entry.func
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   358
    spec = entry.args
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   359
37782
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   360
    args = proto.getargs(spec)
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   361
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   362
    # There is some duplicate boilerplate code here for calling the command and
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   363
    # emitting objects. It is either that or a lot of indented code that looks
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   364
    # like a pyramid (since there are a lot of code paths that result in not
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   365
    # using the cacher).
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   366
    callcommand = lambda: func(repo, proto, **pycompat.strkwargs(args))
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   367
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   368
    # Request is not cacheable. Don't bother instantiating a cacher.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   369
    if not entry.cachekeyfn:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   370
        for o in callcommand():
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   371
            yield o
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   372
        return
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   373
40026
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   374
    if redirect:
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   375
        redirecttargets = redirect[b'targets']
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   376
        redirecthashes = redirect[b'hashes']
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   377
    else:
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   378
        redirecttargets = []
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   379
        redirecthashes = []
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   380
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   381
    cacher = makeresponsecacher(repo, proto, command, args,
40026
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   382
                                cborutil.streamencode,
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   383
                                redirecttargets=redirecttargets,
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   384
                                redirecthashes=redirecthashes)
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   385
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   386
    # But we have no cacher. Do default handling.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   387
    if not cacher:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   388
        for o in callcommand():
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   389
            yield o
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   390
        return
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   391
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   392
    with cacher:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   393
        cachekey = entry.cachekeyfn(repo, proto, cacher, **args)
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   394
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   395
        # No cache key or the cacher doesn't like it. Do default handling.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   396
        if cachekey is None or not cacher.setcachekey(cachekey):
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   397
            for o in callcommand():
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   398
                yield o
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   399
            return
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   400
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   401
        # Serve it from the cache, if possible.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   402
        cached = cacher.lookup()
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   403
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   404
        if cached:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   405
            for o in cached['objs']:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   406
                yield o
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   407
            return
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   408
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   409
        # Else call the command and feed its output into the cacher, allowing
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   410
        # the cacher to buffer/mutate objects as it desires.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   411
        for o in callcommand():
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   412
            for o in cacher.onobject(o):
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   413
                yield o
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   414
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   415
        for o in cacher.onfinished():
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   416
            yield o
37782
99accae4cc59 wireproto: reimplement dispatch() for version 2 server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37781
diff changeset
   417
37810
856f381ad74b interfaceutil: module to stub out zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37784
diff changeset
   418
@interfaceutil.implementer(wireprototypes.baseprotocolhandler)
37296
78103e4138b1 wireproto: port protocol handler to zope.interface
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37295
diff changeset
   419
class httpv2protocolhandler(object):
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   420
    def __init__(self, req, ui, args=None):
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   421
        self._req = req
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   422
        self._ui = ui
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   423
        self._args = args
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   424
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   425
    @property
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   426
    def name(self):
37644
77c9ee77687c wireproto: rename HTTPV2 so it less like HTTP/2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37557
diff changeset
   427
        return HTTP_WIREPROTO_V2
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   428
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   429
    def getargs(self, args):
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   430
        # First look for args that were passed but aren't registered on this
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   431
        # command.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   432
        extra = set(self._args) - set(args)
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   433
        if extra:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   434
            raise error.WireprotoCommandError(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   435
                'unsupported argument to command: %s' %
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   436
                ', '.join(sorted(extra)))
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   437
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   438
        # And look for required arguments that are missing.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   439
        missing = {a for a in args if args[a]['required']} - set(self._args)
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   440
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   441
        if missing:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   442
            raise error.WireprotoCommandError(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   443
                'missing required arguments: %s' % ', '.join(sorted(missing)))
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   444
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   445
        # Now derive the arguments to pass to the command, taking into
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   446
        # account the arguments specified by the client.
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   447
        data = {}
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   448
        for k, meta in sorted(args.items()):
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   449
            # This argument wasn't passed by the client.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   450
            if k not in self._args:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   451
                data[k] = meta['default']()
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   452
                continue
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   453
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   454
            v = self._args[k]
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   455
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   456
            # Sets may be expressed as lists. Silently normalize.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   457
            if meta['type'] == 'set' and isinstance(v, list):
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   458
                v = set(v)
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   459
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   460
            # TODO consider more/stronger type validation.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   461
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   462
            data[k] = v
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   463
37485
0b7475ea38cf wireproto: port heads command to wire protocol v2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37414
diff changeset
   464
        return data
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   465
37393
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   466
    def getprotocaps(self):
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   467
        # Protocol capabilities are currently not implemented for HTTP V2.
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   468
        return set()
afcfdf53e4b5 wireproto: provide accessors for client capabilities
Joerg Sonnenberger <joerg@bec.de>
parents: 37296
diff changeset
   469
37414
2d965bfeb8f6 wireproto: allow direct stream processing for unbundle
Joerg Sonnenberger <joerg@bec.de>
parents: 37393
diff changeset
   470
    def getpayload(self):
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   471
        raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   472
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   473
    @contextlib.contextmanager
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   474
    def mayberedirectstdio(self):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   475
        raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   476
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   477
    def client(self):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   478
        raise NotImplementedError
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   479
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   480
    def addcapabilities(self, repo, caps):
37057
e7a012b60d6e wireproto: implement basic command dispatching for HTTPv2
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37056
diff changeset
   481
        return caps
37050
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   482
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   483
    def checkperm(self, perm):
fddcb51b5084 wireproto: define permissions-based routing of HTTPv2 wire protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37049
diff changeset
   484
        raise NotImplementedError
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   485
37557
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
   486
def httpv2apidescriptor(req, repo):
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
   487
    proto = httpv2protocolhandler(req, repo.ui)
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
   488
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
   489
    return _capabilitiesv2(repo, proto)
734515aca84d wireproto: define and implement HTTP handshake to upgrade protocol
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37546
diff changeset
   490
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   491
def _capabilitiesv2(repo, proto):
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   492
    """Obtain the set of capabilities for version 2 transports.
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   493
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   494
    These capabilities are distinct from the capabilities for version 1
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   495
    transports.
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   496
    """
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   497
    caps = {
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   498
        'commands': {},
37653
b2fa1591fb44 wireproto: add media type to version 2 capabilities response
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37644
diff changeset
   499
        'framingmediatypes': [FRAMINGTYPE],
39816
ae20f52437e9 wireprotov2: advertise recognized path filter prefixes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39815
diff changeset
   500
        'pathfilterprefixes': set(narrowspec.VALID_PREFIXES),
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   501
    }
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   502
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   503
    for command, entry in COMMANDS.items():
39817
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   504
        args = {}
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   505
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   506
        for arg, meta in entry.args.items():
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   507
            args[arg] = {
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   508
                # TODO should this be a normalized type using CBOR's
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   509
                # terminology?
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   510
                b'type': meta['type'],
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   511
                b'required': meta['required'],
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   512
            }
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   513
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   514
            if not meta['required']:
8e7e822e85ec wireprotov2: expose rich arguments metadata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39816
diff changeset
   515
                args[arg][b'default'] = meta['default']()
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   516
39818
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   517
            if meta['validvalues']:
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   518
                args[arg][b'validvalues'] = meta['validvalues']
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   519
40329
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
   520
        # TODO this type of check should be defined in a per-command callback.
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
   521
        if (command == b'rawstorefiledata'
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
   522
            and not streamclone.allowservergeneration(repo)):
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
   523
            continue
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
   524
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   525
        caps['commands'][command] = {
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   526
            'args': args,
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   527
            'permissions': [entry.permission],
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   528
        }
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   529
40172
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   530
        if entry.extracapabilitiesfn:
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   531
            extracaps = entry.extracapabilitiesfn(repo, proto)
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   532
            caps['commands'][command].update(extracaps)
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   533
40050
39074a35f7db wireprotov2: always advertise raw repo requirements
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40026
diff changeset
   534
    caps['rawrepoformats'] = sorted(repo.requirements &
39074a35f7db wireprotov2: always advertise raw repo requirements
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40026
diff changeset
   535
                                    repo.supportedformats)
37657
23c4ddda7bbe wireproto: expose repository formats via capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37653
diff changeset
   536
40024
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   537
    targets = getadvertisedredirecttargets(repo, proto)
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   538
    if targets:
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   539
        caps[b'redirect'] = {
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   540
            b'targets': [],
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   541
            b'hashes': [b'sha256', b'sha1'],
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   542
        }
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   543
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   544
        for target in targets:
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   545
            entry = {
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   546
                b'name': target['name'],
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   547
                b'protocol': target['protocol'],
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   548
                b'uris': target['uris'],
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   549
            }
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   550
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   551
            for key in ('snirequired', 'tlsversions'):
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   552
                if key in target:
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   553
                    entry[key] = target[key]
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   554
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   555
            caps[b'redirect'][b'targets'].append(entry)
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   556
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   557
    return proto.addcapabilities(repo, caps)
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   558
40024
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   559
def getadvertisedredirecttargets(repo, proto):
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   560
    """Obtain a list of content redirect targets.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   561
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   562
    Returns a list containing potential redirect targets that will be
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   563
    advertised in capabilities data. Each dict MUST have the following
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   564
    keys:
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   565
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   566
    name
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   567
       The name of this redirect target. This is the identifier clients use
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   568
       to refer to a target. It is transferred as part of every command
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   569
       request.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   570
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   571
    protocol
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   572
       Network protocol used by this target. Typically this is the string
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   573
       in front of the ``://`` in a URL. e.g. ``https``.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   574
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   575
    uris
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   576
       List of representative URIs for this target. Clients can use the
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   577
       URIs to test parsing for compatibility or for ordering preference
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   578
       for which target to use.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   579
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   580
    The following optional keys are recognized:
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   581
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   582
    snirequired
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   583
       Bool indicating if Server Name Indication (SNI) is required to
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   584
       connect to this target.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   585
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   586
    tlsversions
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   587
       List of bytes indicating which TLS versions are supported by this
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   588
       target.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   589
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   590
    By default, clients reflect the target order advertised by servers
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   591
    and servers will use the first client-advertised target when picking
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   592
    a redirect target. So targets should be advertised in the order the
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   593
    server prefers they be used.
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   594
    """
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   595
    return []
10cf8b116dd8 wireprotov2: advertise redirect targets in capabilities
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40022
diff changeset
   596
40172
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   597
def wireprotocommand(name, args=None, permission='push', cachekeyfn=None,
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   598
                     extracapabilitiesfn=None):
37780
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   599
    """Decorator to declare a wire protocol command.
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   600
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   601
    ``name`` is the name of the wire protocol command being provided.
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   602
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   603
    ``args`` is a dict defining arguments accepted by the command. Keys are
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   604
    the argument name. Values are dicts with the following keys:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   605
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   606
       ``type``
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   607
          The argument data type. Must be one of the following string
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   608
          literals: ``bytes``, ``int``, ``list``, ``dict``, ``set``,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   609
          or ``bool``.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   610
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   611
       ``default``
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   612
          A callable returning the default value for this argument. If not
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   613
          specified, ``None`` will be the default value.
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   614
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   615
       ``example``
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   616
          An example value for this argument.
37780
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   617
39818
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   618
       ``validvalues``
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   619
          Set of recognized values for this argument.
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   620
37780
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   621
    ``permission`` defines the permission type needed to run this command.
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   622
    Can be ``push`` or ``pull``. These roughly map to read-write and read-only,
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   623
    respectively. Default is to assume command requires ``push`` permissions
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   624
    because otherwise commands not declaring their permissions could modify
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   625
    a repository that is supposed to be read-only.
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   626
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   627
    ``cachekeyfn`` defines an optional callable that can derive the
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   628
    cache key for this request.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   629
40172
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   630
    ``extracapabilitiesfn`` defines an optional callable that defines extra
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   631
    command capabilities/parameters that are advertised next to the command
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   632
    in the capabilities data structure describing the server. The callable
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   633
    receives as arguments the repository and protocol objects. It returns
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   634
    a dict of extra fields to add to the command descriptor.
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   635
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   636
    Wire protocol commands are generators of objects to be serialized and
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   637
    sent to the client.
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   638
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   639
    If a command raises an uncaught exception, this will be translated into
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   640
    a command error.
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   641
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   642
    All commands can opt in to being cacheable by defining a function
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   643
    (``cachekeyfn``) that is called to derive a cache key. This function
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   644
    receives the same arguments as the command itself plus a ``cacher``
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   645
    argument containing the active cacher for the request and returns a bytes
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   646
    containing the key in a cache the response to this command may be cached
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   647
    under.
37780
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   648
    """
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   649
    transports = {k for k, v in wireprototypes.TRANSPORTS.items()
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   650
                  if v['version'] == 2}
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   651
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   652
    if permission not in ('push', 'pull'):
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   653
        raise error.ProgrammingError('invalid wire protocol permission; '
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   654
                                     'got %s; expected "push" or "pull"' %
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   655
                                     permission)
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   656
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   657
    if args is None:
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   658
        args = {}
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   659
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   660
    if not isinstance(args, dict):
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   661
        raise error.ProgrammingError('arguments for version 2 commands '
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   662
                                     'must be declared as dicts')
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   663
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   664
    for arg, meta in args.items():
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   665
        if arg == '*':
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   666
            raise error.ProgrammingError('* argument name not allowed on '
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   667
                                         'version 2 commands')
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   668
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   669
        if not isinstance(meta, dict):
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   670
            raise error.ProgrammingError('arguments for version 2 commands '
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   671
                                         'must declare metadata as a dict')
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   672
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   673
        if 'type' not in meta:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   674
            raise error.ProgrammingError('%s argument for command %s does not '
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   675
                                         'declare type field' % (arg, name))
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   676
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   677
        if meta['type'] not in ('bytes', 'int', 'list', 'dict', 'set', 'bool'):
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   678
            raise error.ProgrammingError('%s argument for command %s has '
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   679
                                         'illegal type: %s' % (arg, name,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   680
                                                               meta['type']))
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   681
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   682
        if 'example' not in meta:
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   683
            raise error.ProgrammingError('%s argument for command %s does not '
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   684
                                         'declare example field' % (arg, name))
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   685
39996
582676acaf6d wireprotov2: derive "required" from presence of default value
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39869
diff changeset
   686
        meta['required'] = 'default' not in meta
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   687
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   688
        meta.setdefault('default', lambda: None)
39818
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   689
        meta.setdefault('validvalues', None)
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   690
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   691
    def register(func):
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   692
        if name in COMMANDS:
37780
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   693
            raise error.ProgrammingError('%s command already registered '
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   694
                                         'for version 2' % name)
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   695
37784
ee0d5e9d77b2 wireproto: move version 2 commands dict to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37783
diff changeset
   696
        COMMANDS[name] = wireprototypes.commandentry(
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   697
            func, args=args, transports=transports, permission=permission,
40172
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
   698
            cachekeyfn=cachekeyfn, extracapabilitiesfn=extracapabilitiesfn)
37780
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   699
8acd3a9ac4fd wireproto: make version 2 @wireprotocommand an independent function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37728
diff changeset
   700
        return func
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   701
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   702
    return register
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   703
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   704
def makecommandcachekeyfn(command, localversion=None, allargs=False):
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   705
    """Construct a cache key derivation function with common features.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   706
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   707
    By default, the cache key is a hash of:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   708
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   709
    * The command name.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   710
    * A global cache version number.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   711
    * A local cache version number (passed via ``localversion``).
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   712
    * All the arguments passed to the command.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   713
    * The media type used.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   714
    * Wire protocol version string.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   715
    * The repository path.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   716
    """
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   717
    if not allargs:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   718
        raise error.ProgrammingError('only allargs=True is currently supported')
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   719
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   720
    if localversion is None:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   721
        raise error.ProgrammingError('must set localversion argument value')
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   722
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   723
    def cachekeyfn(repo, proto, cacher, **args):
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   724
        spec = COMMANDS[command]
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   725
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   726
        # Commands that mutate the repo can not be cached.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   727
        if spec.permission == 'push':
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   728
            return None
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   729
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   730
        # TODO config option to disable caching.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   731
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   732
        # Our key derivation strategy is to construct a data structure
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   733
        # holding everything that could influence cacheability and to hash
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   734
        # the CBOR representation of that. Using CBOR seems like it might
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   735
        # be overkill. However, simpler hashing mechanisms are prone to
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   736
        # duplicate input issues. e.g. if you just concatenate two values,
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   737
        # "foo"+"bar" is identical to "fo"+"obar". Using CBOR provides
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   738
        # "padding" between values and prevents these problems.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   739
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   740
        # Seed the hash with various data.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   741
        state = {
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   742
            # To invalidate all cache keys.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   743
            b'globalversion': GLOBAL_CACHE_VERSION,
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   744
            # More granular cache key invalidation.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   745
            b'localversion': localversion,
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   746
            # Cache keys are segmented by command.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   747
            b'command': pycompat.sysbytes(command),
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   748
            # Throw in the media type and API version strings so changes
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   749
            # to exchange semantics invalid cache.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   750
            b'mediatype': FRAMINGTYPE,
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   751
            b'version': HTTP_WIREPROTO_V2,
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   752
            # So same requests for different repos don't share cache keys.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   753
            b'repo': repo.root,
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   754
        }
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   755
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   756
        # The arguments passed to us will have already been normalized.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   757
        # Default values will be set, etc. This is important because it
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   758
        # means that it doesn't matter if clients send an explicit argument
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   759
        # or rely on the default value: it will all normalize to the same
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   760
        # set of arguments on the server and therefore the same cache key.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   761
        #
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   762
        # Arguments by their very nature must support being encoded to CBOR.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   763
        # And the CBOR encoder is deterministic. So we hash the arguments
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   764
        # by feeding the CBOR of their representation into the hasher.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   765
        if allargs:
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   766
            state[b'args'] = pycompat.byteskwargs(args)
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   767
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   768
        cacher.adjustcachekeystate(state)
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   769
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   770
        hasher = hashlib.sha1()
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   771
        for chunk in cborutil.streamencode(state):
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   772
            hasher.update(chunk)
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   773
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   774
        return pycompat.sysbytes(hasher.hexdigest())
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   775
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   776
    return cachekeyfn
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   777
40026
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   778
def makeresponsecacher(repo, proto, command, args, objencoderfn,
b099e6032f38 wireprotov2: server support for sending content redirects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40024
diff changeset
   779
                       redirecttargets, redirecthashes):
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   780
    """Construct a cacher for a cacheable command.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   781
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   782
    Returns an ``iwireprotocolcommandcacher`` instance.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   783
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   784
    Extensions can monkeypatch this function to provide custom caching
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   785
    backends.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   786
    """
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   787
    return None
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
   788
40176
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   789
def resolvenodes(repo, revisions):
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   790
    """Resolve nodes from a revisions specifier data structure."""
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   791
    cl = repo.changelog
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   792
    clhasnode = cl.hasnode
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   793
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   794
    seen = set()
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   795
    nodes = []
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   796
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   797
    if not isinstance(revisions, list):
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   798
        raise error.WireprotoCommandError('revisions must be defined as an '
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   799
                                          'array')
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   800
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   801
    for spec in revisions:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   802
        if b'type' not in spec:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   803
            raise error.WireprotoCommandError(
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   804
                'type key not present in revision specifier')
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   805
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   806
        typ = spec[b'type']
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   807
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   808
        if typ == b'changesetexplicit':
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   809
            if b'nodes' not in spec:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   810
                raise error.WireprotoCommandError(
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   811
                    'nodes key not present in changesetexplicit revision '
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   812
                    'specifier')
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   813
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   814
            for node in spec[b'nodes']:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   815
                if node not in seen:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   816
                    nodes.append(node)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   817
                    seen.add(node)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   818
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   819
        elif typ == b'changesetexplicitdepth':
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   820
            for key in (b'nodes', b'depth'):
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   821
                if key not in spec:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   822
                    raise error.WireprotoCommandError(
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   823
                        '%s key not present in changesetexplicitdepth revision '
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   824
                        'specifier', (key,))
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   825
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   826
            for rev in repo.revs(b'ancestors(%ln, %d)', spec[b'nodes'],
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   827
                                 spec[b'depth'] - 1):
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   828
                node = cl.node(rev)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   829
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   830
                if node not in seen:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   831
                    nodes.append(node)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   832
                    seen.add(node)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   833
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   834
        elif typ == b'changesetdagrange':
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   835
            for key in (b'roots', b'heads'):
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   836
                if key not in spec:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   837
                    raise error.WireprotoCommandError(
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   838
                        '%s key not present in changesetdagrange revision '
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   839
                        'specifier', (key,))
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   840
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   841
            if not spec[b'heads']:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   842
                raise error.WireprotoCommandError(
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   843
                    'heads key in changesetdagrange cannot be empty')
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   844
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   845
            if spec[b'roots']:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   846
                common = [n for n in spec[b'roots'] if clhasnode(n)]
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   847
            else:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   848
                common = [nullid]
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   849
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   850
            for n in discovery.outgoing(repo, common, spec[b'heads']).missing:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   851
                if n not in seen:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   852
                    nodes.append(n)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   853
                    seen.add(n)
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   854
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   855
        else:
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   856
            raise error.WireprotoCommandError(
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   857
                'unknown revision specifier type: %s', (typ,))
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   858
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   859
    return nodes
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   860
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   861
@wireprotocommand('branchmap', permission='pull')
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   862
def branchmapv2(repo, proto):
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   863
    yield {encoding.fromlocal(k): v
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   864
           for k, v in repo.branchmap().iteritems()}
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   865
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   866
@wireprotocommand('capabilities', permission='pull')
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   867
def capabilitiesv2(repo, proto):
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
   868
    yield _capabilitiesv2(repo, proto)
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
   869
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   870
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   871
    'changesetdata',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   872
    args={
40176
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   873
        'revisions': {
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   874
            'type': 'list',
40176
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   875
            'example': [{
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   876
                b'type': b'changesetexplicit',
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   877
                b'nodes': [b'abcdef...'],
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   878
            }],
39820
d3d333ab167a wireprotov2: teach changesetdata to fetch ancestors until depth
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39819
diff changeset
   879
        },
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   880
        'fields': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   881
            'type': 'set',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   882
            'default': set,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   883
            'example': {b'parents', b'revision'},
39818
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   884
            'validvalues': {b'bookmarks', b'parents', b'phase', b'revision'},
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   885
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   886
    },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
   887
    permission='pull')
40176
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   888
def changesetdata(repo, proto, revisions, fields):
39652
399ddd3227a4 wireprotov2: add TODOs around extending changesetdata fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39650
diff changeset
   889
    # TODO look for unknown fields and abort when they can't be serviced.
39818
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
   890
    # This could probably be validated by dispatcher using validvalues.
39652
399ddd3227a4 wireprotov2: add TODOs around extending changesetdata fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39650
diff changeset
   891
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   892
    cl = repo.changelog
40176
41263df08109 wireprotov2: change how revisions are specified to changesetdata
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40175
diff changeset
   893
    outgoing = resolvenodes(repo, revisions)
39648
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   894
    publishing = repo.publishing()
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   895
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   896
    if outgoing:
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   897
        repo.hook('preoutgoing', throw=True, source='serve')
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   898
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   899
    yield {
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   900
        b'totalitems': len(outgoing),
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   901
    }
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   902
39648
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   903
    # The phases of nodes already transferred to the client may have changed
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   904
    # since the client last requested data. We send phase-only records
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   905
    # for these revisions, if requested.
40175
6c42409691ec wireprotov2: stop sending phase updates for base revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40172
diff changeset
   906
    # TODO actually do this. We'll probably want to emit phase heads
6c42409691ec wireprotov2: stop sending phase updates for base revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40172
diff changeset
   907
    # in the ancestry set of the outgoing revisions. This will ensure
6c42409691ec wireprotov2: stop sending phase updates for base revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40172
diff changeset
   908
    # that phase updates within that set are seen.
6c42409691ec wireprotov2: stop sending phase updates for base revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40172
diff changeset
   909
    if b'phase' in fields:
6c42409691ec wireprotov2: stop sending phase updates for base revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40172
diff changeset
   910
        pass
39648
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   911
39650
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   912
    nodebookmarks = {}
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   913
    for mark, node in repo._bookmarks.items():
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   914
        nodebookmarks.setdefault(node, set()).add(mark)
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   915
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   916
    # It is already topologically sorted by revision number.
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   917
    for node in outgoing:
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   918
        d = {
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   919
            b'node': node,
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   920
        }
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   921
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   922
        if b'parents' in fields:
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   923
            d[b'parents'] = cl.parents(node)
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   924
39648
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   925
        if b'phase' in fields:
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   926
            if publishing:
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   927
                d[b'phase'] = b'public'
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   928
            else:
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   929
                ctx = repo[node]
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   930
                d[b'phase'] = ctx.phasestr()
c1aacb0d76ff wireprotov2: add phases to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39646
diff changeset
   931
39650
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   932
        if b'bookmarks' in fields and node in nodebookmarks:
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   933
            d[b'bookmarks'] = sorted(nodebookmarks[node])
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   934
            del nodebookmarks[node]
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   935
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   936
        followingmeta = []
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   937
        followingdata = []
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   938
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   939
        if b'revision' in fields:
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   940
            revisiondata = cl.revision(node, raw=True)
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   941
            followingmeta.append((b'revision', len(revisiondata)))
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   942
            followingdata.append(revisiondata)
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   943
39652
399ddd3227a4 wireprotov2: add TODOs around extending changesetdata fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39650
diff changeset
   944
        # TODO make it possible for extensions to wrap a function or register
399ddd3227a4 wireprotov2: add TODOs around extending changesetdata fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39650
diff changeset
   945
        # a handler to service custom fields.
399ddd3227a4 wireprotov2: add TODOs around extending changesetdata fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39650
diff changeset
   946
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   947
        if followingmeta:
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   948
            d[b'fieldsfollowing'] = followingmeta
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   949
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   950
        yield d
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   951
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   952
        for extra in followingdata:
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
   953
            yield extra
39646
9c2c77c73f23 wireprotov2: define and implement "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39575
diff changeset
   954
39650
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   955
    # If requested, send bookmarks from nodes that didn't have revision
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   956
    # data sent so receiver is aware of any bookmark updates.
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   957
    if b'bookmarks' in fields:
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   958
        for node, marks in sorted(nodebookmarks.iteritems()):
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   959
            yield {
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   960
                b'node': node,
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   961
                b'bookmarks': sorted(marks),
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   962
            }
9dffa99f9158 wireprotov2: add bookmarks to "changesetdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39648
diff changeset
   963
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   964
class FileAccessError(Exception):
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   965
    """Represents an error accessing a specific file."""
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   966
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   967
    def __init__(self, path, msg, args):
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   968
        self.path = path
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   969
        self.msg = msg
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   970
        self.args = args
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   971
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   972
def getfilestore(repo, proto, path):
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   973
    """Obtain a file storage object for use with wire protocol.
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   974
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   975
    Exists as a standalone function so extensions can monkeypatch to add
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   976
    access control.
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   977
    """
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   978
    # This seems to work even if the file doesn't exist. So catch
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   979
    # "empty" files and return an error.
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   980
    fl = repo.file(path)
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   981
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   982
    if not len(fl):
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   983
        raise FileAccessError(path, 'unknown file: %s', (path,))
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   984
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   985
    return fl
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
   986
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
   987
def emitfilerevisions(repo, path, revisions, linknodes, fields):
40177
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   988
    for revision in revisions:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   989
        d = {
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   990
            b'node': revision.node,
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   991
        }
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   992
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   993
        if b'parents' in fields:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   994
            d[b'parents'] = [revision.p1node, revision.p2node]
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   995
40391
abbd077965c0 wireprotov2: support exposing linknode of file revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40329
diff changeset
   996
        if b'linknode' in fields:
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
   997
            d[b'linknode'] = linknodes[revision.node]
40391
abbd077965c0 wireprotov2: support exposing linknode of file revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40329
diff changeset
   998
40177
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
   999
        followingmeta = []
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1000
        followingdata = []
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1001
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1002
        if b'revision' in fields:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1003
            if revision.revision is not None:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1004
                followingmeta.append((b'revision', len(revision.revision)))
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1005
                followingdata.append(revision.revision)
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1006
            else:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1007
                d[b'deltabasenode'] = revision.basenode
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1008
                followingmeta.append((b'delta', len(revision.delta)))
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1009
                followingdata.append(revision.delta)
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1010
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1011
        if followingmeta:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1012
            d[b'fieldsfollowing'] = followingmeta
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1013
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1014
        yield d
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1015
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1016
        for extra in followingdata:
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1017
            yield extra
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1018
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1019
def makefilematcher(repo, pathfilter):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1020
    """Construct a matcher from a path filter dict."""
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1021
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1022
    # Validate values.
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1023
    if pathfilter:
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1024
        for key in (b'include', b'exclude'):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1025
            for pattern in pathfilter.get(key, []):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1026
                if not pattern.startswith((b'path:', b'rootfilesin:')):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1027
                    raise error.WireprotoCommandError(
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1028
                        '%s pattern must begin with `path:` or `rootfilesin:`; '
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1029
                        'got %s', (key, pattern))
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1030
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1031
    if pathfilter:
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1032
        matcher = matchmod.match(repo.root, b'',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1033
                                 include=pathfilter.get(b'include', []),
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1034
                                 exclude=pathfilter.get(b'exclude', []))
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1035
    else:
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1036
        matcher = matchmod.match(repo.root, b'')
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1037
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1038
    # Requested patterns could include files not in the local store. So
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1039
    # filter those out.
40692
f83cea7f54d7 wireprotov2server: let repo.narrowmatch(match) do matcher intersection
Martin von Zweigbergk <martinvonz@google.com>
parents: 40391
diff changeset
  1040
    return repo.narrowmatch(matcher)
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1041
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1042
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1043
    'filedata',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1044
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1045
        'haveparents': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1046
            'type': 'bool',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1047
            'default': lambda: False,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1048
            'example': True,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1049
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1050
        'nodes': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1051
            'type': 'list',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1052
            'example': [b'0123456...'],
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1053
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1054
        'fields': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1055
            'type': 'set',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1056
            'default': set,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1057
            'example': {b'parents', b'revision'},
40391
abbd077965c0 wireprotov2: support exposing linknode of file revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40329
diff changeset
  1058
            'validvalues': {b'parents', b'revision', b'linknode'},
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1059
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1060
        'path': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1061
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1062
            'example': b'foo.txt',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1063
        }
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1064
    },
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
  1065
    permission='pull',
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
  1066
    # TODO censoring a file revision won't invalidate the cache.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
  1067
    # Figure out a way to take censoring into account when deriving
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
  1068
    # the cache key.
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
  1069
    cachekeyfn=makecommandcachekeyfn('filedata', 1, allargs=True))
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1070
def filedata(repo, proto, haveparents, nodes, fields, path):
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1071
    # TODO this API allows access to file revisions that are attached to
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1072
    # secret changesets. filesdata does not have this problem. Maybe this
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1073
    # API should be deleted?
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1074
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1075
    try:
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1076
        # Extensions may wish to access the protocol handler.
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1077
        store = getfilestore(repo, proto, path)
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1078
    except FileAccessError as e:
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1079
        raise error.WireprotoCommandError(e.msg, e.args)
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1080
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1081
    clnode = repo.changelog.node
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1082
    linknodes = {}
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1083
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1084
    # Validate requested nodes.
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1085
    for node in nodes:
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1086
        try:
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1087
            store.rev(node)
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1088
        except error.LookupError:
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1089
            raise error.WireprotoCommandError('unknown file node: %s',
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1090
                                              (hex(node),))
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1091
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1092
        # TODO by creating the filectx against a specific file revision
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1093
        # instead of changeset, linkrev() is always used. This is wrong for
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1094
        # cases where linkrev() may refer to a hidden changeset. But since this
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1095
        # API doesn't know anything about changesets, we're not sure how to
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1096
        # disambiguate the linknode. Perhaps we should delete this API?
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1097
        fctx = repo.filectx(path, fileid=node)
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1098
        linknodes[node] = clnode(fctx.introrev())
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1099
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1100
    revisions = store.emitrevisions(nodes,
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1101
                                    revisiondata=b'revision' in fields,
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1102
                                    assumehaveparentrevisions=haveparents)
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1103
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1104
    yield {
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1105
        b'totalitems': len(nodes),
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1106
    }
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1107
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1108
    for o in emitfilerevisions(repo, path, revisions, linknodes, fields):
40177
41e2633bcd00 wireprotov2: extract file object emission to own function
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40176
diff changeset
  1109
        yield o
39655
0e03e6a44dee wireprotov2: define and implement "filedata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39653
diff changeset
  1110
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1111
def filesdatacapabilities(repo, proto):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1112
    batchsize = repo.ui.configint(
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1113
        b'experimental', b'server.filesdata.recommended-batch-size')
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1114
    return {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1115
        b'recommendedbatchsize': batchsize,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1116
    }
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1117
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1118
@wireprotocommand(
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1119
    'filesdata',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1120
    args={
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1121
        'haveparents': {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1122
            'type': 'bool',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1123
            'default': lambda: False,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1124
            'example': True,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1125
        },
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1126
        'fields': {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1127
            'type': 'set',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1128
            'default': set,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1129
            'example': {b'parents', b'revision'},
40391
abbd077965c0 wireprotov2: support exposing linknode of file revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40329
diff changeset
  1130
            'validvalues': {b'firstchangeset', b'linknode', b'parents',
abbd077965c0 wireprotov2: support exposing linknode of file revisions
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40329
diff changeset
  1131
                            b'revision'},
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1132
        },
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1133
        'pathfilter': {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1134
            'type': 'dict',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1135
            'default': lambda: None,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1136
            'example': {b'include': [b'path:tests']},
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1137
        },
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1138
        'revisions': {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1139
            'type': 'list',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1140
            'example': [{
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1141
                b'type': b'changesetexplicit',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1142
                b'nodes': [b'abcdef...'],
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1143
            }],
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1144
        },
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1145
    },
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1146
    permission='pull',
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1147
    # TODO censoring a file revision won't invalidate the cache.
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1148
    # Figure out a way to take censoring into account when deriving
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1149
    # the cache key.
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1150
    cachekeyfn=makecommandcachekeyfn('filesdata', 1, allargs=True),
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1151
    extracapabilitiesfn=filesdatacapabilities)
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1152
def filesdata(repo, proto, haveparents, fields, pathfilter, revisions):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1153
    # TODO This should operate on a repo that exposes obsolete changesets. There
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1154
    # is a race between a client making a push that obsoletes a changeset and
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1155
    # another client fetching files data for that changeset. If a client has a
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1156
    # changeset, it should probably be allowed to access files data for that
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1157
    # changeset.
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1158
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1159
    outgoing = resolvenodes(repo, revisions)
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1160
    filematcher = makefilematcher(repo, pathfilter)
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1161
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1162
    # path -> {fnode: linknode}
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1163
    fnodes = collections.defaultdict(dict)
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1164
40942
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1165
    # We collect the set of relevant file revisions by iterating the changeset
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1166
    # revisions and either walking the set of files recorded in the changeset
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1167
    # or by walking the manifest at that revision. There is probably room for a
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1168
    # storage-level API to request this data, as it can be expensive to compute
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1169
    # and would benefit from caching or alternate storage from what revlogs
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1170
    # provide.
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1171
    for node in outgoing:
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1172
        ctx = repo[node]
40942
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1173
        mctx = ctx.manifestctx()
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1174
        md = mctx.read()
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1175
40942
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1176
        if haveparents:
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1177
            checkpaths = ctx.files()
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1178
        else:
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1179
            checkpaths = md.keys()
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1180
40942
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1181
        for path in checkpaths:
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1182
            fnode = md[path]
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1183
40942
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1184
            if path in fnodes and fnode in fnodes[path]:
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1185
                continue
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1186
40942
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1187
            if not filematcher(path):
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1188
                continue
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1189
08cfa77d7288 wireprotov2: unify file revision collection and linknode derivation
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40941
diff changeset
  1190
            fnodes[path].setdefault(fnode, node)
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1191
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1192
    yield {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1193
        b'totalpaths': len(fnodes),
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1194
        b'totalitems': sum(len(v) for v in fnodes.values())
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1195
    }
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1196
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1197
    for path, filenodes in sorted(fnodes.items()):
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1198
        try:
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1199
            store = getfilestore(repo, proto, path)
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1200
        except FileAccessError as e:
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1201
            raise error.WireprotoCommandError(e.msg, e.args)
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1202
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1203
        yield {
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1204
            b'path': path,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1205
            b'totalitems': len(filenodes),
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1206
        }
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1207
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1208
        revisions = store.emitrevisions(filenodes.keys(),
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1209
                                        revisiondata=b'revision' in fields,
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1210
                                        assumehaveparentrevisions=haveparents)
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1211
40941
3ed77780f4a6 wireprotov2: send linknodes to emitfilerevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40692
diff changeset
  1212
        for o in emitfilerevisions(repo, path, revisions, filenodes, fields):
40178
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1213
            yield o
46a40bce3ae0 wireprotov2: define and implement "filesdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40177
diff changeset
  1214
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1215
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1216
    'heads',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1217
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1218
        'publiconly': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1219
            'type': 'bool',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1220
            'default': lambda: False,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1221
            'example': False,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1222
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1223
    },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1224
    permission='pull')
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1225
def headsv2(repo, proto, publiconly):
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1226
    if publiconly:
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1227
        repo = repo.filtered('immutable')
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1228
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1229
    yield repo.heads()
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1230
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1231
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1232
    'known',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1233
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1234
        'nodes': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1235
            'type': 'list',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1236
            'default': list,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1237
            'example': [b'deadbeef'],
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1238
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1239
    },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1240
    permission='pull')
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1241
def knownv2(repo, proto, nodes):
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1242
    result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1243
    yield result
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1244
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1245
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1246
    'listkeys',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1247
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1248
        'namespace': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1249
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1250
            'example': b'ns',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1251
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1252
    },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1253
    permission='pull')
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1254
def listkeysv2(repo, proto, namespace):
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1255
    keys = repo.listkeys(encoding.tolocal(namespace))
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1256
    keys = {encoding.fromlocal(k): encoding.fromlocal(v)
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1257
            for k, v in keys.iteritems()}
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1258
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1259
    yield keys
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1260
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1261
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1262
    'lookup',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1263
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1264
        'key': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1265
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1266
            'example': b'foo',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1267
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1268
    },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1269
    permission='pull')
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1270
def lookupv2(repo, proto, key):
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1271
    key = encoding.tolocal(key)
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1272
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1273
    # TODO handle exception.
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1274
    node = repo.lookup(key)
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1275
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1276
    yield node
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1277
40172
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1278
def manifestdatacapabilities(repo, proto):
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1279
    batchsize = repo.ui.configint(
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1280
        b'experimental', b'server.manifestdata.recommended-batch-size')
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1281
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1282
    return {
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1283
        b'recommendedbatchsize': batchsize,
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1284
    }
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1285
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1286
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1287
    'manifestdata',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1288
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1289
        'nodes': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1290
            'type': 'list',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1291
            'example': [b'0123456...'],
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1292
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1293
        'haveparents': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1294
            'type': 'bool',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1295
            'default': lambda: False,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1296
            'example': True,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1297
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1298
        'fields': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1299
            'type': 'set',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1300
            'default': set,
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1301
            'example': {b'parents', b'revision'},
39818
c30faea8d02d wireprotov2: advertise set of valid values for requestable fields
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39817
diff changeset
  1302
            'validvalues': {b'parents', b'revision'},
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1303
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1304
        'tree': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1305
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1306
            'example': b'',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1307
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1308
    },
40022
c537144fdbef wireprotov2: support response caching
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39996
diff changeset
  1309
    permission='pull',
40172
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1310
    cachekeyfn=makecommandcachekeyfn('manifestdata', 1, allargs=True),
30f70d11c224 wireprotov2: advertise recommended batch size for requests
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40138
diff changeset
  1311
    extracapabilitiesfn=manifestdatacapabilities)
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1312
def manifestdata(repo, proto, haveparents, nodes, fields, tree):
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1313
    store = repo.manifestlog.getstorage(tree)
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1314
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1315
    # Validate the node is known and abort on unknown revisions.
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1316
    for node in nodes:
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1317
        try:
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1318
            store.rev(node)
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1319
        except error.LookupError:
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1320
            raise error.WireprotoCommandError(
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1321
                'unknown node: %s', (node,))
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1322
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1323
    revisions = store.emitrevisions(nodes,
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1324
                                    revisiondata=b'revision' in fields,
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1325
                                    assumehaveparentrevisions=haveparents)
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1326
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1327
    yield {
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1328
        b'totalitems': len(nodes),
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1329
    }
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1330
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1331
    for revision in revisions:
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1332
        d = {
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1333
            b'node': revision.node,
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1334
        }
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1335
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1336
        if b'parents' in fields:
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1337
            d[b'parents'] = [revision.p1node, revision.p2node]
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1338
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1339
        followingmeta = []
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1340
        followingdata = []
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1341
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1342
        if b'revision' in fields:
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1343
            if revision.revision is not None:
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1344
                followingmeta.append((b'revision', len(revision.revision)))
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1345
                followingdata.append(revision.revision)
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1346
            else:
39869
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1347
                d[b'deltabasenode'] = revision.basenode
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1348
                followingmeta.append((b'delta', len(revision.delta)))
7b752bf08435 wireprotov2server: port to emitrevisions()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39842
diff changeset
  1349
                followingdata.append(revision.delta)
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1350
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1351
        if followingmeta:
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1352
            d[b'fieldsfollowing'] = followingmeta
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1353
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1354
        yield d
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1355
39819
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1356
        for extra in followingdata:
d059cb669632 wireprotov2: allow multiple fields to follow revision maps
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39818
diff changeset
  1357
            yield extra
39653
c7a7c7e844e5 wireprotov2: define and implement "manifestdata" command
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39652
diff changeset
  1358
39815
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1359
@wireprotocommand(
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1360
    'pushkey',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1361
    args={
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1362
        'namespace': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1363
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1364
            'example': b'ns',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1365
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1366
        'key': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1367
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1368
            'example': b'key',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1369
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1370
        'old': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1371
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1372
            'example': b'old',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1373
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1374
        'new': {
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1375
            'type': 'bytes',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1376
            'example': 'new',
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1377
        },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1378
    },
0b61d21f05cc wireprotov2: declare command arguments richly
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39657
diff changeset
  1379
    permission='push')
37546
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1380
def pushkeyv2(repo, proto, namespace, key, old, new):
3a2367e6c6f2 wireproto: move version 2 command handlers to wireprotov2server
Gregory Szorc <gregory.szorc@gmail.com>
parents: 37545
diff changeset
  1381
    # TODO handle ui output redirection
39575
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1382
    yield repo.pushkey(encoding.tolocal(namespace),
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1383
                       encoding.tolocal(key),
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1384
                       encoding.tolocal(old),
07b58266bce3 wireprotov2: implement commands as a generator of objects
Gregory Szorc <gregory.szorc@gmail.com>
parents: 39467
diff changeset
  1385
                       encoding.tolocal(new))
40329
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1386
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1387
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1388
@wireprotocommand(
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1389
    'rawstorefiledata',
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1390
    args={
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1391
        'files': {
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1392
            'type': 'list',
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1393
            'example': [b'changelog', b'manifestlog'],
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1394
        },
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1395
        'pathfilter': {
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1396
            'type': 'list',
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1397
            'default': lambda: None,
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1398
            'example': {b'include': [b'path:tests']},
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1399
        },
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1400
    },
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1401
    permission='pull')
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1402
def rawstorefiledata(repo, proto, files, pathfilter):
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1403
    if not streamclone.allowservergeneration(repo):
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1404
        raise error.WireprotoCommandError(b'stream clone is disabled')
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1405
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1406
    # TODO support dynamically advertising what store files "sets" are
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1407
    # available. For now, we support changelog, manifestlog, and files.
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1408
    files = set(files)
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1409
    allowedfiles = {b'changelog', b'manifestlog'}
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1410
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1411
    unsupported = files - allowedfiles
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1412
    if unsupported:
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1413
        raise error.WireprotoCommandError(b'unknown file type: %s',
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1414
                                          (b', '.join(sorted(unsupported)),))
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1415
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1416
    with repo.lock():
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1417
        topfiles = list(repo.store.topfiles())
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1418
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1419
    sendfiles = []
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1420
    totalsize = 0
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1421
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1422
    # TODO this is a bunch of storage layer interface abstractions because
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1423
    # it assumes revlogs.
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1424
    for name, encodedname, size in topfiles:
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1425
        if b'changelog' in files and name.startswith(b'00changelog'):
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1426
            pass
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1427
        elif b'manifestlog' in files and name.startswith(b'00manifest'):
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1428
            pass
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1429
        else:
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1430
            continue
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1431
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1432
        sendfiles.append((b'store', name, size))
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1433
        totalsize += size
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1434
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1435
    yield {
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1436
        b'filecount': len(sendfiles),
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1437
        b'totalsize': totalsize,
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1438
    }
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1439
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1440
    for location, name, size in sendfiles:
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1441
        yield {
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1442
            b'location': location,
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1443
            b'path': name,
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1444
            b'size': size,
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1445
        }
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1446
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1447
        # We have to use a closure for this to ensure the context manager is
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1448
        # closed only after sending the final chunk.
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1449
        def getfiledata():
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1450
            with repo.svfs(name, 'rb', auditpath=False) as fh:
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1451
                for chunk in util.filechunkiter(fh, limit=size):
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1452
                    yield chunk
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1453
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1454
        yield wireprototypes.indefinitebytestringresponse(
ed55a0077490 wireprotov2: implement command for retrieving raw store files
Gregory Szorc <gregory.szorc@gmail.com>
parents: 40178
diff changeset
  1455
            getfiledata())