annotate mercurial/wireprotov2server.py @ 41403:e82288a9556c

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