##// END OF EJS Templates
wireproto: define and expose types of wire command arguments...
Gregory Szorc -
r37553:69e46c18 default
parent child Browse files
Show More
@@ -1712,7 +1712,12 b' commands'
1712 1712 are:
1713 1713
1714 1714 args
1715 An array of argument names accepted by this command.
1715 A map of argument names and their expected types.
1716
1717 Types are defined as a representative value for the expected type.
1718 e.g. an argument expecting a boolean type will have its value
1719 set to true. An integer type will have its value set to 42. The
1720 actual values are arbitrary and may not have meaning.
1716 1721 permissions
1717 1722 An array of permissions required to execute this command.
1718 1723
@@ -713,8 +713,11 b" def wireprotocommand(name, args='', tran"
713 713
714 714 ``name`` is the name of the wire protocol command being provided.
715 715
716 ``args`` is a space-delimited list of named arguments that the command
717 accepts. ``*`` is a special value that says to accept all arguments.
716 ``args`` defines the named arguments accepted by the command. It is
717 ideally a dict mapping argument names to their types. For backwards
718 compatibility, it can be a space-delimited list of argument names. For
719 version 1 transports, ``*`` denotes a special value that says to accept
720 all named arguments.
718 721
719 722 ``transportpolicy`` is a POLICY_* constant denoting which transports
720 723 this wire protocol command should be exposed to. By default, commands
@@ -752,6 +755,17 b" def wireprotocommand(name, args='', tran"
752 755 'got %s; expected "push" or "pull"' %
753 756 permission)
754 757
758 if 1 in transportversions and not isinstance(args, bytes):
759 raise error.ProgrammingError('arguments for version 1 commands must '
760 'be declared as bytes')
761
762 if isinstance(args, bytes):
763 dictargs = {arg: b'legacy' for arg in args.split()}
764 elif isinstance(args, dict):
765 dictargs = args
766 else:
767 raise ValueError('args must be bytes or a dict')
768
755 769 def register(func):
756 770 if 1 in transportversions:
757 771 if name in commands:
@@ -764,7 +778,8 b" def wireprotocommand(name, args='', tran"
764 778 if name in commandsv2:
765 779 raise error.ProgrammingError('%s command already registered '
766 780 'for version 2' % name)
767 commandsv2[name] = commandentry(func, args=args,
781
782 commandsv2[name] = commandentry(func, args=dictargs,
768 783 transports=transports,
769 784 permission=permission)
770 785
@@ -1304,7 +1319,7 b' def _capabilitiesv2(repo, proto):'
1304 1319
1305 1320 for command, entry in commandsv2.items():
1306 1321 caps['commands'][command] = {
1307 'args': sorted(entry.args.split()) if entry.args else [],
1322 'args': entry.args,
1308 1323 'permissions': [entry.permission],
1309 1324 }
1310 1325
@@ -1325,7 +1340,11 b' def capabilitiesv2(repo, proto):'
1325 1340
1326 1341 return wireprototypes.cborresponse(caps)
1327 1342
1328 @wireprotocommand('heads', args='publiconly', permission='pull',
1343 @wireprotocommand('heads',
1344 args={
1345 'publiconly': False,
1346 },
1347 permission='pull',
1329 1348 transportpolicy=POLICY_V2_ONLY)
1330 1349 def headsv2(repo, proto, publiconly=False):
1331 1350 if publiconly:
@@ -1333,14 +1352,22 b' def headsv2(repo, proto, publiconly=Fals'
1333 1352
1334 1353 return wireprototypes.cborresponse(repo.heads())
1335 1354
1336 @wireprotocommand('known', 'nodes', permission='pull',
1355 @wireprotocommand('known',
1356 args={
1357 'nodes': [b'deadbeef'],
1358 },
1359 permission='pull',
1337 1360 transportpolicy=POLICY_V2_ONLY)
1338 1361 def knownv2(repo, proto, nodes=None):
1339 1362 nodes = nodes or []
1340 1363 result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
1341 1364 return wireprototypes.cborresponse(result)
1342 1365
1343 @wireprotocommand('listkeys', 'namespace', permission='pull',
1366 @wireprotocommand('listkeys',
1367 args={
1368 'namespace': b'ns',
1369 },
1370 permission='pull',
1344 1371 transportpolicy=POLICY_V2_ONLY)
1345 1372 def listkeysv2(repo, proto, namespace=None):
1346 1373 keys = repo.listkeys(encoding.tolocal(namespace))
@@ -606,10 +606,11 b' class httpv2protocolhandler(object):'
606 606
607 607 def getargs(self, args):
608 608 data = {}
609 for k in args.split():
609 for k, typ in args.items():
610 610 if k == '*':
611 611 raise NotImplementedError('do not support * args')
612 612 elif k in self._args:
613 # TODO consider validating value types.
613 614 data[k] = self._args[k]
614 615
615 616 return data
@@ -30,11 +30,11 b' capabilities request returns an array of'
30 30 s> \r\n
31 31 s> *\r\n (glob)
32 32 s> *\x00\x01\x00\x02\x01F (glob)
33 s> \xa2Hcommands\xaaEheads\xa2Dargs\x81JpubliconlyKpermissions\x81DpullEknown\xa2Dargs\x81EnodesKpermissions\x81DpullFlookup\xa2Dargs\x81CkeyKpermissions\x81DpullGpushkey\xa2Dargs\x84CkeyInamespaceCnewColdKpermissions\x81DpushHlistkeys\xa2Dargs\x81InamespaceKpermissions\x81DpullHunbundle\xa2Dargs\x81EheadsKpermissions\x81DpushIbranchmap\xa2Dargs\x80Kpermissions\x81DpullIgetbundle\xa2Dargs\x81A*Kpermissions\x81DpullLcapabilities\xa2Dargs\x80Kpermissions\x81DpullLclonebundles\xa2Dargs\x80Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlib
33 s> \xa2Hcommands\xaaEheads\xa2Dargs\xa1Jpubliconly\xf4Kpermissions\x81DpullEknown\xa2Dargs\xa1Enodes\x81HdeadbeefKpermissions\x81DpullFlookup\xa2Dargs\xa1CkeyFlegacyKpermissions\x81DpullGpushkey\xa2Dargs\xa4CkeyFlegacyCnewFlegacyColdFlegacyInamespaceFlegacyKpermissions\x81DpushHlistkeys\xa2Dargs\xa1InamespaceBnsKpermissions\x81DpullHunbundle\xa2Dargs\xa1EheadsFlegacyKpermissions\x81DpushIbranchmap\xa2Dargs\xa0Kpermissions\x81DpullIgetbundle\xa2Dargs\xa1A*FlegacyKpermissions\x81DpullLcapabilities\xa2Dargs\xa0Kpermissions\x81DpullLclonebundles\xa2Dargs\xa0Kpermissions\x81DpullKcompression\x82\xa1DnameDzstd\xa1DnameDzlib
34 34 s> \r\n
35 35 received frame(size=*; request=1; stream=2; streamflags=stream-begin; type=bytes-response; flags=eos|cbor) (glob)
36 36 s> 0\r\n
37 37 s> \r\n
38 response: [{b'commands': {b'branchmap': {b'args': [], b'permissions': [b'pull']}, b'capabilities': {b'args': [], b'permissions': [b'pull']}, b'clonebundles': {b'args': [], b'permissions': [b'pull']}, b'getbundle': {b'args': [b'*'], b'permissions': [b'pull']}, b'heads': {b'args': [b'publiconly'], b'permissions': [b'pull']}, b'known': {b'args': [b'nodes'], b'permissions': [b'pull']}, b'listkeys': {b'args': [b'namespace'], b'permissions': [b'pull']}, b'lookup': {b'args': [b'key'], b'permissions': [b'pull']}, b'pushkey': {b'args': [b'key', b'namespace', b'new', b'old'], b'permissions': [b'push']}, b'unbundle': {b'args': [b'heads'], b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}]}]
38 response: [{b'commands': {b'branchmap': {b'args': {}, b'permissions': [b'pull']}, b'capabilities': {b'args': {}, b'permissions': [b'pull']}, b'clonebundles': {b'args': {}, b'permissions': [b'pull']}, b'getbundle': {b'args': {b'*': b'legacy'}, b'permissions': [b'pull']}, b'heads': {b'args': {b'publiconly': False}, b'permissions': [b'pull']}, b'known': {b'args': {b'nodes': [b'deadbeef']}, b'permissions': [b'pull']}, b'listkeys': {b'args': {b'namespace': b'ns'}, b'permissions': [b'pull']}, b'lookup': {b'args': {b'key': b'legacy'}, b'permissions': [b'pull']}, b'pushkey': {b'args': {b'key': b'legacy', b'namespace': b'legacy', b'new': b'legacy', b'old': b'legacy'}, b'permissions': [b'push']}, b'unbundle': {b'args': {b'heads': b'legacy'}, b'permissions': [b'push']}}, b'compression': [{b'name': b'zstd'}, {b'name': b'zlib'}]}]
39 39
40 40 $ cat error.log
General Comments 0
You need to be logged in to leave comments. Login now