mercurial/wireproto.py
changeset 37779 379d54eae6eb
parent 37614 a81d02ea65db
child 37780 8acd3a9ac4fd
equal deleted inserted replaced
37778:f10cb49951e1 37779:379d54eae6eb
   344 
   344 
   345         return func
   345         return func
   346     return register
   346     return register
   347 
   347 
   348 # TODO define a more appropriate permissions type to use for this.
   348 # TODO define a more appropriate permissions type to use for this.
   349 @wireprotocommand('batch', 'cmds *', permission='pull',
   349 @wireprotocommand('batch', 'cmds *', permission='pull')
   350                   transportpolicy=POLICY_V1_ONLY)
       
   351 def batch(repo, proto, cmds, others):
   350 def batch(repo, proto, cmds, others):
   352     unescapearg = wireprototypes.unescapebatcharg
   351     unescapearg = wireprototypes.unescapebatcharg
   353     repo = repo.filtered("served")
   352     repo = repo.filtered("served")
   354     res = []
   353     res = []
   355     for pair in cmds.split(';'):
   354     for pair in cmds.split(';'):
   391             result = result.data
   390             result = result.data
   392         res.append(wireprototypes.escapebatcharg(result))
   391         res.append(wireprototypes.escapebatcharg(result))
   393 
   392 
   394     return wireprototypes.bytesresponse(';'.join(res))
   393     return wireprototypes.bytesresponse(';'.join(res))
   395 
   394 
   396 @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY,
   395 @wireprotocommand('between', 'pairs', permission='pull')
   397                   permission='pull')
       
   398 def between(repo, proto, pairs):
   396 def between(repo, proto, pairs):
   399     pairs = [wireprototypes.decodelist(p, '-') for p in pairs.split(" ")]
   397     pairs = [wireprototypes.decodelist(p, '-') for p in pairs.split(" ")]
   400     r = []
   398     r = []
   401     for b in repo.between(pairs):
   399     for b in repo.between(pairs):
   402         r.append(wireprototypes.encodelist(b) + "\n")
   400         r.append(wireprototypes.encodelist(b) + "\n")
   403 
   401 
   404     return wireprototypes.bytesresponse(''.join(r))
   402     return wireprototypes.bytesresponse(''.join(r))
   405 
   403 
   406 @wireprotocommand('branchmap', permission='pull',
   404 @wireprotocommand('branchmap', permission='pull')
   407                   transportpolicy=POLICY_V1_ONLY)
       
   408 def branchmap(repo, proto):
   405 def branchmap(repo, proto):
   409     branchmap = repo.branchmap()
   406     branchmap = repo.branchmap()
   410     heads = []
   407     heads = []
   411     for branch, nodes in branchmap.iteritems():
   408     for branch, nodes in branchmap.iteritems():
   412         branchname = urlreq.quote(encoding.fromlocal(branch))
   409         branchname = urlreq.quote(encoding.fromlocal(branch))
   413         branchnodes = wireprototypes.encodelist(nodes)
   410         branchnodes = wireprototypes.encodelist(nodes)
   414         heads.append('%s %s' % (branchname, branchnodes))
   411         heads.append('%s %s' % (branchname, branchnodes))
   415 
   412 
   416     return wireprototypes.bytesresponse('\n'.join(heads))
   413     return wireprototypes.bytesresponse('\n'.join(heads))
   417 
   414 
   418 @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY,
   415 @wireprotocommand('branches', 'nodes', permission='pull')
   419                   permission='pull')
       
   420 def branches(repo, proto, nodes):
   416 def branches(repo, proto, nodes):
   421     nodes = wireprototypes.decodelist(nodes)
   417     nodes = wireprototypes.decodelist(nodes)
   422     r = []
   418     r = []
   423     for b in repo.branches(nodes):
   419     for b in repo.branches(nodes):
   424         r.append(wireprototypes.encodelist(b) + "\n")
   420         r.append(wireprototypes.encodelist(b) + "\n")
   425 
   421 
   426     return wireprototypes.bytesresponse(''.join(r))
   422     return wireprototypes.bytesresponse(''.join(r))
   427 
   423 
   428 @wireprotocommand('clonebundles', '', permission='pull',
   424 @wireprotocommand('clonebundles', '', permission='pull')
   429                   transportpolicy=POLICY_V1_ONLY)
       
   430 def clonebundles(repo, proto):
   425 def clonebundles(repo, proto):
   431     """Server command for returning info for available bundles to seed clones.
   426     """Server command for returning info for available bundles to seed clones.
   432 
   427 
   433     Clients will parse this response and determine what bundle to fetch.
   428     Clients will parse this response and determine what bundle to fetch.
   434 
   429 
   477 
   472 
   478     return proto.addcapabilities(repo, caps)
   473     return proto.addcapabilities(repo, caps)
   479 
   474 
   480 # If you are writing an extension and consider wrapping this function. Wrap
   475 # If you are writing an extension and consider wrapping this function. Wrap
   481 # `_capabilities` instead.
   476 # `_capabilities` instead.
   482 @wireprotocommand('capabilities', permission='pull',
   477 @wireprotocommand('capabilities', permission='pull')
   483                   transportpolicy=POLICY_V1_ONLY)
       
   484 def capabilities(repo, proto):
   478 def capabilities(repo, proto):
   485     caps = _capabilities(repo, proto)
   479     caps = _capabilities(repo, proto)
   486     return wireprototypes.bytesresponse(' '.join(sorted(caps)))
   480     return wireprototypes.bytesresponse(' '.join(sorted(caps)))
   487 
   481 
   488 @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY,
   482 @wireprotocommand('changegroup', 'roots', permission='pull')
   489                   permission='pull')
       
   490 def changegroup(repo, proto, roots):
   483 def changegroup(repo, proto, roots):
   491     nodes = wireprototypes.decodelist(roots)
   484     nodes = wireprototypes.decodelist(roots)
   492     outgoing = discovery.outgoing(repo, missingroots=nodes,
   485     outgoing = discovery.outgoing(repo, missingroots=nodes,
   493                                   missingheads=repo.heads())
   486                                   missingheads=repo.heads())
   494     cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
   487     cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
   495     gen = iter(lambda: cg.read(32768), '')
   488     gen = iter(lambda: cg.read(32768), '')
   496     return wireprototypes.streamres(gen=gen)
   489     return wireprototypes.streamres(gen=gen)
   497 
   490 
   498 @wireprotocommand('changegroupsubset', 'bases heads',
   491 @wireprotocommand('changegroupsubset', 'bases heads',
   499                   transportpolicy=POLICY_V1_ONLY,
       
   500                   permission='pull')
   492                   permission='pull')
   501 def changegroupsubset(repo, proto, bases, heads):
   493 def changegroupsubset(repo, proto, bases, heads):
   502     bases = wireprototypes.decodelist(bases)
   494     bases = wireprototypes.decodelist(bases)
   503     heads = wireprototypes.decodelist(heads)
   495     heads = wireprototypes.decodelist(heads)
   504     outgoing = discovery.outgoing(repo, missingroots=bases,
   496     outgoing = discovery.outgoing(repo, missingroots=bases,
   506     cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
   498     cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
   507     gen = iter(lambda: cg.read(32768), '')
   499     gen = iter(lambda: cg.read(32768), '')
   508     return wireprototypes.streamres(gen=gen)
   500     return wireprototypes.streamres(gen=gen)
   509 
   501 
   510 @wireprotocommand('debugwireargs', 'one two *',
   502 @wireprotocommand('debugwireargs', 'one two *',
   511                   permission='pull', transportpolicy=POLICY_V1_ONLY)
   503                   permission='pull')
   512 def debugwireargs(repo, proto, one, two, others):
   504 def debugwireargs(repo, proto, one, two, others):
   513     # only accept optional args from the known set
   505     # only accept optional args from the known set
   514     opts = options('debugwireargs', ['three', 'four'], others)
   506     opts = options('debugwireargs', ['three', 'four'], others)
   515     return wireprototypes.bytesresponse(repo.debugwireargs(
   507     return wireprototypes.bytesresponse(repo.debugwireargs(
   516         one, two, **pycompat.strkwargs(opts)))
   508         one, two, **pycompat.strkwargs(opts)))
   577         except IOError:
   569         except IOError:
   578             repo.ui.debug('pullbundle "%s" not accessible\n' % path)
   570             repo.ui.debug('pullbundle "%s" not accessible\n' % path)
   579             continue
   571             continue
   580     return None
   572     return None
   581 
   573 
   582 @wireprotocommand('getbundle', '*', permission='pull',
   574 @wireprotocommand('getbundle', '*', permission='pull')
   583                   transportpolicy=POLICY_V1_ONLY)
       
   584 def getbundle(repo, proto, others):
   575 def getbundle(repo, proto, others):
   585     opts = options('getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(),
   576     opts = options('getbundle', wireprototypes.GETBUNDLE_ARGUMENTS.keys(),
   586                    others)
   577                    others)
   587     for k, v in opts.iteritems():
   578     for k, v in opts.iteritems():
   588         keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k]
   579         keytype = wireprototypes.GETBUNDLE_ARGUMENTS[k]
   654         prefercompressed = False
   645         prefercompressed = False
   655 
   646 
   656     return wireprototypes.streamres(
   647     return wireprototypes.streamres(
   657         gen=chunks, prefer_uncompressed=not prefercompressed)
   648         gen=chunks, prefer_uncompressed=not prefercompressed)
   658 
   649 
   659 @wireprotocommand('heads', permission='pull', transportpolicy=POLICY_V1_ONLY)
   650 @wireprotocommand('heads', permission='pull')
   660 def heads(repo, proto):
   651 def heads(repo, proto):
   661     h = repo.heads()
   652     h = repo.heads()
   662     return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + '\n')
   653     return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + '\n')
   663 
   654 
   664 @wireprotocommand('hello', permission='pull', transportpolicy=POLICY_V1_ONLY)
   655 @wireprotocommand('hello', permission='pull')
   665 def hello(repo, proto):
   656 def hello(repo, proto):
   666     """Called as part of SSH handshake to obtain server info.
   657     """Called as part of SSH handshake to obtain server info.
   667 
   658 
   668     Returns a list of lines describing interesting things about the
   659     Returns a list of lines describing interesting things about the
   669     server, in an RFC822-like format.
   660     server, in an RFC822-like format.
   674         capabilities: <token0> <token1> <token2>
   665         capabilities: <token0> <token1> <token2>
   675     """
   666     """
   676     caps = capabilities(repo, proto).data
   667     caps = capabilities(repo, proto).data
   677     return wireprototypes.bytesresponse('capabilities: %s\n' % caps)
   668     return wireprototypes.bytesresponse('capabilities: %s\n' % caps)
   678 
   669 
   679 @wireprotocommand('listkeys', 'namespace', permission='pull',
   670 @wireprotocommand('listkeys', 'namespace', permission='pull')
   680                   transportpolicy=POLICY_V1_ONLY)
       
   681 def listkeys(repo, proto, namespace):
   671 def listkeys(repo, proto, namespace):
   682     d = sorted(repo.listkeys(encoding.tolocal(namespace)).items())
   672     d = sorted(repo.listkeys(encoding.tolocal(namespace)).items())
   683     return wireprototypes.bytesresponse(pushkeymod.encodekeys(d))
   673     return wireprototypes.bytesresponse(pushkeymod.encodekeys(d))
   684 
   674 
   685 @wireprotocommand('lookup', 'key', permission='pull',
   675 @wireprotocommand('lookup', 'key', permission='pull')
   686                   transportpolicy=POLICY_V1_ONLY)
       
   687 def lookup(repo, proto, key):
   676 def lookup(repo, proto, key):
   688     try:
   677     try:
   689         k = encoding.tolocal(key)
   678         k = encoding.tolocal(key)
   690         n = repo.lookup(k)
   679         n = repo.lookup(k)
   691         r = hex(n)
   680         r = hex(n)
   693     except Exception as inst:
   682     except Exception as inst:
   694         r = stringutil.forcebytestr(inst)
   683         r = stringutil.forcebytestr(inst)
   695         success = 0
   684         success = 0
   696     return wireprototypes.bytesresponse('%d %s\n' % (success, r))
   685     return wireprototypes.bytesresponse('%d %s\n' % (success, r))
   697 
   686 
   698 @wireprotocommand('known', 'nodes *', permission='pull',
   687 @wireprotocommand('known', 'nodes *', permission='pull')
   699                   transportpolicy=POLICY_V1_ONLY)
       
   700 def known(repo, proto, nodes, others):
   688 def known(repo, proto, nodes, others):
   701     v = ''.join(b and '1' or '0'
   689     v = ''.join(b and '1' or '0'
   702                 for b in repo.known(wireprototypes.decodelist(nodes)))
   690                 for b in repo.known(wireprototypes.decodelist(nodes)))
   703     return wireprototypes.bytesresponse(v)
   691     return wireprototypes.bytesresponse(v)
   704 
   692 
   705 @wireprotocommand('protocaps', 'caps', permission='pull',
   693 @wireprotocommand('protocaps', 'caps', permission='pull')
   706                   transportpolicy=POLICY_V1_ONLY)
       
   707 def protocaps(repo, proto, caps):
   694 def protocaps(repo, proto, caps):
   708     if proto.name == wireprototypes.SSHV1:
   695     if proto.name == wireprototypes.SSHV1:
   709         proto._protocaps = set(caps.split(' '))
   696         proto._protocaps = set(caps.split(' '))
   710     return wireprototypes.bytesresponse('OK')
   697     return wireprototypes.bytesresponse('OK')
   711 
   698 
   712 @wireprotocommand('pushkey', 'namespace key old new', permission='push',
   699 @wireprotocommand('pushkey', 'namespace key old new', permission='push')
   713                   transportpolicy=POLICY_V1_ONLY)
       
   714 def pushkey(repo, proto, namespace, key, old, new):
   700 def pushkey(repo, proto, namespace, key, old, new):
   715     # compatibility with pre-1.8 clients which were accidentally
   701     # compatibility with pre-1.8 clients which were accidentally
   716     # sending raw binary nodes rather than utf-8-encoded hex
   702     # sending raw binary nodes rather than utf-8-encoded hex
   717     if len(new) == 20 and stringutil.escapestr(new) != new:
   703     if len(new) == 20 and stringutil.escapestr(new) != new:
   718         # looks like it could be a binary node
   704         # looks like it could be a binary node
   729                          encoding.tolocal(old), new) or False
   715                          encoding.tolocal(old), new) or False
   730 
   716 
   731     output = output.getvalue() if output else ''
   717     output = output.getvalue() if output else ''
   732     return wireprototypes.bytesresponse('%d\n%s' % (int(r), output))
   718     return wireprototypes.bytesresponse('%d\n%s' % (int(r), output))
   733 
   719 
   734 @wireprotocommand('stream_out', permission='pull',
   720 @wireprotocommand('stream_out', permission='pull')
   735                   transportpolicy=POLICY_V1_ONLY)
       
   736 def stream(repo, proto):
   721 def stream(repo, proto):
   737     '''If the server supports streaming clone, it advertises the "stream"
   722     '''If the server supports streaming clone, it advertises the "stream"
   738     capability with a value representing the version and flags of the repo
   723     capability with a value representing the version and flags of the repo
   739     it is serving. Client checks to see if it understands the format.
   724     it is serving. Client checks to see if it understands the format.
   740     '''
   725     '''
   741     return wireprototypes.streamreslegacy(
   726     return wireprototypes.streamreslegacy(
   742         streamclone.generatev1wireproto(repo))
   727         streamclone.generatev1wireproto(repo))
   743 
   728 
   744 @wireprotocommand('unbundle', 'heads', permission='push',
   729 @wireprotocommand('unbundle', 'heads', permission='push')
   745                   transportpolicy=POLICY_V1_ONLY)
       
   746 def unbundle(repo, proto, heads):
   730 def unbundle(repo, proto, heads):
   747     their_heads = wireprototypes.decodelist(heads)
   731     their_heads = wireprototypes.decodelist(heads)
   748 
   732 
   749     with proto.mayberedirectstdio() as output:
   733     with proto.mayberedirectstdio() as output:
   750         try:
   734         try: