comparison mercurial/wireprotov2server.py @ 37784:ee0d5e9d77b2

wireproto: move version 2 commands dict to wireprotov2server This was the final piece of version 2 referenced in wireproto. The break between server implementations is now much cleaner. Differential Revision: https://phab.mercurial-scm.org/D3399
author Gregory Szorc <gregory.szorc@gmail.com>
date Mon, 16 Apr 2018 22:10:02 -0700
parents 9d818539abfa
children 856f381ad74b
comparison
equal deleted inserted replaced
37783:9d818539abfa 37784:ee0d5e9d77b2
19 encoding, 19 encoding,
20 error, 20 error,
21 pycompat, 21 pycompat,
22 streamclone, 22 streamclone,
23 util, 23 util,
24 wireproto,
25 wireprotoframing, 24 wireprotoframing,
26 wireprototypes, 25 wireprototypes,
27 ) 26 )
28 27
29 FRAMINGTYPE = b'application/mercurial-exp-framing-0005' 28 FRAMINGTYPE = b'application/mercurial-exp-framing-0005'
30 29
31 HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2 30 HTTP_WIREPROTO_V2 = wireprototypes.HTTP_WIREPROTO_V2
31
32 COMMANDS = wireprototypes.commanddict()
32 33
33 def handlehttpv2request(rctx, req, res, checkperm, urlparts): 34 def handlehttpv2request(rctx, req, res, checkperm, urlparts):
34 from .hgweb import common as hgwebcommon 35 from .hgweb import common as hgwebcommon
35 36
36 # URL space looks like: <permissions>/<command>, where <permission> can 37 # URL space looks like: <permissions>/<command>, where <permission> can
85 # Extra commands that we handle that aren't really wire protocol 86 # Extra commands that we handle that aren't really wire protocol
86 # commands. Think extra hard before making this hackery available to 87 # commands. Think extra hard before making this hackery available to
87 # extension. 88 # extension.
88 extracommands = {'multirequest'} 89 extracommands = {'multirequest'}
89 90
90 if command not in wireproto.commandsv2 and command not in extracommands: 91 if command not in COMMANDS and command not in extracommands:
91 res.status = b'404 Not Found' 92 res.status = b'404 Not Found'
92 res.headers[b'Content-Type'] = b'text/plain' 93 res.headers[b'Content-Type'] = b'text/plain'
93 res.setbodybytes(_('unknown wire protocol command: %s\n') % command) 94 res.setbodybytes(_('unknown wire protocol command: %s\n') % command)
94 return 95 return
95 96
96 repo = rctx.repo 97 repo = rctx.repo
97 ui = repo.ui 98 ui = repo.ui
98 99
99 proto = httpv2protocolhandler(req, ui) 100 proto = httpv2protocolhandler(req, ui)
100 101
101 if (not wireproto.commandsv2.commandavailable(command, proto) 102 if (not COMMANDS.commandavailable(command, proto)
102 and command not in extracommands): 103 and command not in extracommands):
103 res.status = b'404 Not Found' 104 res.status = b'404 Not Found'
104 res.headers[b'Content-Type'] = b'text/plain' 105 res.headers[b'Content-Type'] = b'text/plain'
105 res.setbodybytes(_('invalid wire protocol command: %s') % command) 106 res.setbodybytes(_('invalid wire protocol command: %s') % command)
106 return 107 return
252 # iff each command is the same. 253 # iff each command is the same.
253 254
254 proto = httpv2protocolhandler(req, ui, args=command['args']) 255 proto = httpv2protocolhandler(req, ui, args=command['args'])
255 256
256 if reqcommand == b'multirequest': 257 if reqcommand == b'multirequest':
257 if not wireproto.commandsv2.commandavailable(command['command'], proto): 258 if not COMMANDS.commandavailable(command['command'], proto):
258 # TODO proper error mechanism 259 # TODO proper error mechanism
259 res.status = b'200 OK' 260 res.status = b'200 OK'
260 res.headers[b'Content-Type'] = b'text/plain' 261 res.headers[b'Content-Type'] = b'text/plain'
261 res.setbodybytes(_('wire protocol command not available: %s') % 262 res.setbodybytes(_('wire protocol command not available: %s') %
262 command['command']) 263 command['command'])
263 return True 264 return True
264 265
265 # TODO don't use assert here, since it may be elided by -O. 266 # TODO don't use assert here, since it may be elided by -O.
266 assert authedperm in (b'ro', b'rw') 267 assert authedperm in (b'ro', b'rw')
267 wirecommand = wireproto.commandsv2[command['command']] 268 wirecommand = COMMANDS[command['command']]
268 assert wirecommand.permission in ('push', 'pull') 269 assert wirecommand.permission in ('push', 'pull')
269 270
270 if authedperm == b'ro' and wirecommand.permission != 'pull': 271 if authedperm == b'ro' and wirecommand.permission != 'pull':
271 # TODO proper error mechanism 272 # TODO proper error mechanism
272 res.status = b'403 Forbidden' 273 res.status = b'403 Forbidden'
332 return repo.filtered('served') 333 return repo.filtered('served')
333 334
334 def dispatch(repo, proto, command): 335 def dispatch(repo, proto, command):
335 repo = getdispatchrepo(repo, proto, command) 336 repo = getdispatchrepo(repo, proto, command)
336 337
337 func, spec = wireproto.commandsv2[command] 338 func, spec = COMMANDS[command]
338 args = proto.getargs(spec) 339 args = proto.getargs(spec)
339 340
340 return func(repo, proto, **args) 341 return func(repo, proto, **args)
341 342
342 @zi.implementer(wireprototypes.baseprotocolhandler) 343 @zi.implementer(wireprototypes.baseprotocolhandler)
402 'commands': {}, 403 'commands': {},
403 'compression': compression, 404 'compression': compression,
404 'framingmediatypes': [FRAMINGTYPE], 405 'framingmediatypes': [FRAMINGTYPE],
405 } 406 }
406 407
407 for command, entry in wireproto.commandsv2.items(): 408 for command, entry in COMMANDS.items():
408 caps['commands'][command] = { 409 caps['commands'][command] = {
409 'args': entry.args, 410 'args': entry.args,
410 'permissions': [entry.permission], 411 'permissions': [entry.permission],
411 } 412 }
412 413
443 if not isinstance(args, dict): 444 if not isinstance(args, dict):
444 raise error.ProgrammingError('arguments for version 2 commands ' 445 raise error.ProgrammingError('arguments for version 2 commands '
445 'must be declared as dicts') 446 'must be declared as dicts')
446 447
447 def register(func): 448 def register(func):
448 if name in wireproto.commandsv2: 449 if name in COMMANDS:
449 raise error.ProgrammingError('%s command already registered ' 450 raise error.ProgrammingError('%s command already registered '
450 'for version 2' % name) 451 'for version 2' % name)
451 452
452 wireproto.commandsv2[name] = wireprototypes.commandentry( 453 COMMANDS[name] = wireprototypes.commandentry(
453 func, args=args, transports=transports, permission=permission) 454 func, args=args, transports=transports, permission=permission)
454 455
455 return func 456 return func
456 457
457 return register 458 return register