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: |