Show More
@@ -251,32 +251,20 b' class commanddict(dict):' | |||||
251 |
|
251 | |||
252 | return True |
|
252 | return True | |
253 |
|
253 | |||
254 | # Constants specifying which transports a wire protocol command should be |
|
|||
255 | # available on. For use with @wireprotocommand. |
|
|||
256 | POLICY_V1_ONLY = 'v1-only' |
|
|||
257 | POLICY_V2_ONLY = 'v2-only' |
|
|||
258 |
|
||||
259 | # For version 1 transports. |
|
254 | # For version 1 transports. | |
260 | commands = commanddict() |
|
255 | commands = commanddict() | |
261 |
|
256 | |||
262 | # For version 2 transports. |
|
257 | # For version 2 transports. | |
263 | commandsv2 = commanddict() |
|
258 | commandsv2 = commanddict() | |
264 |
|
259 | |||
265 |
def wireprotocommand(name, args=None, |
|
260 | def wireprotocommand(name, args=None, permission='push'): | |
266 | permission='push'): |
|
|||
267 | """Decorator to declare a wire protocol command. |
|
261 | """Decorator to declare a wire protocol command. | |
268 |
|
262 | |||
269 | ``name`` is the name of the wire protocol command being provided. |
|
263 | ``name`` is the name of the wire protocol command being provided. | |
270 |
|
264 | |||
271 | ``args`` defines the named arguments accepted by the command. It is |
|
265 | ``args`` defines the named arguments accepted by the command. It is | |
272 | ideally a dict mapping argument names to their types. For backwards |
|
266 | a space-delimited list of argument names. ``*`` denotes a special value | |
273 | compatibility, it can be a space-delimited list of argument names. For |
|
267 | that says to accept all named arguments. | |
274 | version 1 transports, ``*`` denotes a special value that says to accept |
|
|||
275 | all named arguments. |
|
|||
276 |
|
||||
277 | ``transportpolicy`` is a POLICY_* constant denoting which transports |
|
|||
278 | this wire protocol command should be exposed to. By default, commands |
|
|||
279 | are exposed to all wire protocol transports. |
|
|||
280 |
|
268 | |||
281 | ``permission`` defines the permission type needed to run this command. |
|
269 | ``permission`` defines the permission type needed to run this command. | |
282 | Can be ``push`` or ``pull``. These roughly map to read-write and read-only, |
|
270 | Can be ``push`` or ``pull``. These roughly map to read-write and read-only, | |
@@ -284,17 +272,8 b' def wireprotocommand(name, args=None, tr' | |||||
284 | because otherwise commands not declaring their permissions could modify |
|
272 | because otherwise commands not declaring their permissions could modify | |
285 | a repository that is supposed to be read-only. |
|
273 | a repository that is supposed to be read-only. | |
286 | """ |
|
274 | """ | |
287 | if transportpolicy == POLICY_V1_ONLY: |
|
275 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() | |
288 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() |
|
276 | if v['version'] == 1} | |
289 | if v['version'] == 1} |
|
|||
290 | transportversion = 1 |
|
|||
291 | elif transportpolicy == POLICY_V2_ONLY: |
|
|||
292 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() |
|
|||
293 | if v['version'] == 2} |
|
|||
294 | transportversion = 2 |
|
|||
295 | else: |
|
|||
296 | raise error.ProgrammingError('invalid transport policy value: %s' % |
|
|||
297 | transportpolicy) |
|
|||
298 |
|
277 | |||
299 | # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to |
|
278 | # Because SSHv2 is a mirror of SSHv1, we allow "batch" commands through to | |
300 | # SSHv2. |
|
279 | # SSHv2. | |
@@ -307,40 +286,20 b' def wireprotocommand(name, args=None, tr' | |||||
307 | 'got %s; expected "push" or "pull"' % |
|
286 | 'got %s; expected "push" or "pull"' % | |
308 | permission) |
|
287 | permission) | |
309 |
|
288 | |||
310 | if transportversion == 1: |
|
289 | if args is None: | |
311 |
|
|
290 | args = '' | |
312 | args = '' |
|
|||
313 |
|
291 | |||
314 |
|
|
292 | if not isinstance(args, bytes): | |
315 |
|
|
293 | raise error.ProgrammingError('arguments for version 1 commands ' | |
316 |
|
|
294 | 'must be declared as bytes') | |
317 | elif transportversion == 2: |
|
|||
318 | if args is None: |
|
|||
319 | args = {} |
|
|||
320 |
|
||||
321 | if not isinstance(args, dict): |
|
|||
322 | raise error.ProgrammingError('arguments for version 2 commands ' |
|
|||
323 | 'must be declared as dicts') |
|
|||
324 |
|
295 | |||
325 | def register(func): |
|
296 | def register(func): | |
326 | if transportversion == 1: |
|
297 | if name in commands: | |
327 | if name in commands: |
|
298 | raise error.ProgrammingError('%s command already registered ' | |
328 | raise error.ProgrammingError('%s command already registered ' |
|
299 | 'for version 1' % name) | |
329 | 'for version 1' % name) |
|
300 | commands[name] = commandentry(func, args=args, | |
330 | commands[name] = commandentry(func, args=args, |
|
301 | transports=transports, | |
331 |
|
|
302 | permission=permission) | |
332 | permission=permission) |
|
|||
333 | elif transportversion == 2: |
|
|||
334 | if name in commandsv2: |
|
|||
335 | raise error.ProgrammingError('%s command already registered ' |
|
|||
336 | 'for version 2' % name) |
|
|||
337 |
|
||||
338 | commandsv2[name] = commandentry(func, args=args, |
|
|||
339 | transports=transports, |
|
|||
340 | permission=permission) |
|
|||
341 | else: |
|
|||
342 | raise error.ProgrammingError('unhandled transport version: %d' % |
|
|||
343 | transportversion) |
|
|||
344 |
|
303 | |||
345 | return func |
|
304 | return func | |
346 | return register |
|
305 | return register |
@@ -405,10 +405,43 b' def _capabilitiesv2(repo, proto):' | |||||
405 |
|
405 | |||
406 | return proto.addcapabilities(repo, caps) |
|
406 | return proto.addcapabilities(repo, caps) | |
407 |
|
407 | |||
408 |
def wireprotocommand( |
|
408 | def wireprotocommand(name, args=None, permission='push'): | |
|
409 | """Decorator to declare a wire protocol command. | |||
|
410 | ||||
|
411 | ``name`` is the name of the wire protocol command being provided. | |||
|
412 | ||||
|
413 | ``args`` is a dict of argument names to example values. | |||
|
414 | ||||
|
415 | ``permission`` defines the permission type needed to run this command. | |||
|
416 | Can be ``push`` or ``pull``. These roughly map to read-write and read-only, | |||
|
417 | respectively. Default is to assume command requires ``push`` permissions | |||
|
418 | because otherwise commands not declaring their permissions could modify | |||
|
419 | a repository that is supposed to be read-only. | |||
|
420 | """ | |||
|
421 | transports = {k for k, v in wireprototypes.TRANSPORTS.items() | |||
|
422 | if v['version'] == 2} | |||
|
423 | ||||
|
424 | if permission not in ('push', 'pull'): | |||
|
425 | raise error.ProgrammingError('invalid wire protocol permission; ' | |||
|
426 | 'got %s; expected "push" or "pull"' % | |||
|
427 | permission) | |||
|
428 | ||||
|
429 | if args is None: | |||
|
430 | args = {} | |||
|
431 | ||||
|
432 | if not isinstance(args, dict): | |||
|
433 | raise error.ProgrammingError('arguments for version 2 commands ' | |||
|
434 | 'must be declared as dicts') | |||
|
435 | ||||
409 | def register(func): |
|
436 | def register(func): | |
410 |
|
|
437 | if name in wireproto.commandsv2: | |
411 | *args, transportpolicy=wireproto.POLICY_V2_ONLY, **kwargs)(func) |
|
438 | raise error.ProgrammingError('%s command already registered ' | |
|
439 | 'for version 2' % name) | |||
|
440 | ||||
|
441 | wireproto.commandsv2[name] = wireproto.commandentry( | |||
|
442 | func, args=args, transports=transports, permission=permission) | |||
|
443 | ||||
|
444 | return func | |||
412 |
|
445 | |||
413 | return register |
|
446 | return register | |
414 |
|
447 |
@@ -16,6 +16,7 b' sendhttpv2peerhandshake() {' | |||||
16 | cat > dummycommands.py << EOF |
|
16 | cat > dummycommands.py << EOF | |
17 | from mercurial import ( |
|
17 | from mercurial import ( | |
18 | wireprototypes, |
|
18 | wireprototypes, | |
|
19 | wireprotov2server, | |||
19 | wireproto, |
|
20 | wireproto, | |
20 | ) |
|
21 | ) | |
21 |
|
22 | |||
@@ -23,8 +24,7 b' from mercurial import (' | |||||
23 | def customreadonlyv1(repo, proto): |
|
24 | def customreadonlyv1(repo, proto): | |
24 | return wireprototypes.bytesresponse(b'customreadonly bytes response') |
|
25 | return wireprototypes.bytesresponse(b'customreadonly bytes response') | |
25 |
|
26 | |||
26 |
@wireproto.wireprotocommand('customreadonly', permission='pull' |
|
27 | @wireprotov2server.wireprotocommand('customreadonly', permission='pull') | |
27 | transportpolicy=wireproto.POLICY_V2_ONLY) |
|
|||
28 | def customreadonlyv2(repo, proto): |
|
28 | def customreadonlyv2(repo, proto): | |
29 | return wireprototypes.cborresponse(b'customreadonly bytes response') |
|
29 | return wireprototypes.cborresponse(b'customreadonly bytes response') | |
30 |
|
30 | |||
@@ -32,8 +32,7 b' def customreadonlyv2(repo, proto):' | |||||
32 | def customreadwrite(repo, proto): |
|
32 | def customreadwrite(repo, proto): | |
33 | return wireprototypes.bytesresponse(b'customreadwrite bytes response') |
|
33 | return wireprototypes.bytesresponse(b'customreadwrite bytes response') | |
34 |
|
34 | |||
35 |
@wireproto.wireprotocommand('customreadwrite', permission='push' |
|
35 | @wireprotov2server.wireprotocommand('customreadwrite', permission='push') | |
36 | transportpolicy=wireproto.POLICY_V2_ONLY) |
|
|||
37 | def customreadwritev2(repo, proto): |
|
36 | def customreadwritev2(repo, proto): | |
38 | return wireprototypes.cborresponse(b'customreadwrite bytes response') |
|
37 | return wireprototypes.cborresponse(b'customreadwrite bytes response') | |
39 | EOF |
|
38 | EOF |
General Comments 0
You need to be logged in to leave comments.
Login now