mercurial/wireproto.py
changeset 37535 69e46c1834ac
parent 37534 465187fec06f
child 37536 2003da12f49b
equal deleted inserted replaced
37534:465187fec06f 37535:69e46c1834ac
   711                      permission='push'):
   711                      permission='push'):
   712     """Decorator to declare a wire protocol command.
   712     """Decorator to declare a wire protocol command.
   713 
   713 
   714     ``name`` is the name of the wire protocol command being provided.
   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
   716     ``args`` defines the named arguments accepted by the command. It is
   717     accepts. ``*`` is a special value that says to accept all arguments.
   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     ``transportpolicy`` is a POLICY_* constant denoting which transports
   722     ``transportpolicy`` is a POLICY_* constant denoting which transports
   720     this wire protocol command should be exposed to. By default, commands
   723     this wire protocol command should be exposed to. By default, commands
   721     are exposed to all wire protocol transports.
   724     are exposed to all wire protocol transports.
   722 
   725 
   750     if permission not in ('push', 'pull'):
   753     if permission not in ('push', 'pull'):
   751         raise error.ProgrammingError('invalid wire protocol permission; '
   754         raise error.ProgrammingError('invalid wire protocol permission; '
   752                                      'got %s; expected "push" or "pull"' %
   755                                      'got %s; expected "push" or "pull"' %
   753                                      permission)
   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     def register(func):
   769     def register(func):
   756         if 1 in transportversions:
   770         if 1 in transportversions:
   757             if name in commands:
   771             if name in commands:
   758                 raise error.ProgrammingError('%s command already registered '
   772                 raise error.ProgrammingError('%s command already registered '
   759                                              'for version 1' % name)
   773                                              'for version 1' % name)
   762                                           permission=permission)
   776                                           permission=permission)
   763         if 2 in transportversions:
   777         if 2 in transportversions:
   764             if name in commandsv2:
   778             if name in commandsv2:
   765                 raise error.ProgrammingError('%s command already registered '
   779                 raise error.ProgrammingError('%s command already registered '
   766                                              'for version 2' % name)
   780                                              'for version 2' % name)
   767             commandsv2[name] = commandentry(func, args=args,
   781 
       
   782             commandsv2[name] = commandentry(func, args=dictargs,
   768                                             transports=transports,
   783                                             transports=transports,
   769                                             permission=permission)
   784                                             permission=permission)
   770 
   785 
   771         return func
   786         return func
   772     return register
   787     return register
  1302         'compression': compression,
  1317         'compression': compression,
  1303     }
  1318     }
  1304 
  1319 
  1305     for command, entry in commandsv2.items():
  1320     for command, entry in commandsv2.items():
  1306         caps['commands'][command] = {
  1321         caps['commands'][command] = {
  1307             'args': sorted(entry.args.split()) if entry.args else [],
  1322             'args': entry.args,
  1308             'permissions': [entry.permission],
  1323             'permissions': [entry.permission],
  1309         }
  1324         }
  1310 
  1325 
  1311     return proto.addcapabilities(repo, caps)
  1326     return proto.addcapabilities(repo, caps)
  1312 
  1327 
  1323 def capabilitiesv2(repo, proto):
  1338 def capabilitiesv2(repo, proto):
  1324     caps = _capabilitiesv2(repo, proto)
  1339     caps = _capabilitiesv2(repo, proto)
  1325 
  1340 
  1326     return wireprototypes.cborresponse(caps)
  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                   transportpolicy=POLICY_V2_ONLY)
  1348                   transportpolicy=POLICY_V2_ONLY)
  1330 def headsv2(repo, proto, publiconly=False):
  1349 def headsv2(repo, proto, publiconly=False):
  1331     if publiconly:
  1350     if publiconly:
  1332         repo = repo.filtered('immutable')
  1351         repo = repo.filtered('immutable')
  1333 
  1352 
  1334     return wireprototypes.cborresponse(repo.heads())
  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                   transportpolicy=POLICY_V2_ONLY)
  1360                   transportpolicy=POLICY_V2_ONLY)
  1338 def knownv2(repo, proto, nodes=None):
  1361 def knownv2(repo, proto, nodes=None):
  1339     nodes = nodes or []
  1362     nodes = nodes or []
  1340     result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
  1363     result = b''.join(b'1' if n else b'0' for n in repo.known(nodes))
  1341     return wireprototypes.cborresponse(result)
  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                   transportpolicy=POLICY_V2_ONLY)
  1371                   transportpolicy=POLICY_V2_ONLY)
  1345 def listkeysv2(repo, proto, namespace=None):
  1372 def listkeysv2(repo, proto, namespace=None):
  1346     keys = repo.listkeys(encoding.tolocal(namespace))
  1373     keys = repo.listkeys(encoding.tolocal(namespace))
  1347     keys = {encoding.fromlocal(k): encoding.fromlocal(v)
  1374     keys = {encoding.fromlocal(k): encoding.fromlocal(v)
  1348             for k, v in keys.iteritems()}
  1375             for k, v in keys.iteritems()}