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