##// END OF EJS Templates
wireprotov2server: port to emitrevisions()...
Gregory Szorc -
r39900:7b752bf0 default
parent child Browse files
Show More
@@ -12,11 +12,8 b' from .i18n import _'
12 from .node import (
12 from .node import (
13 hex,
13 hex,
14 nullid,
14 nullid,
15 nullrev,
16 )
15 )
17 from . import (
16 from . import (
18 changegroup,
19 dagop,
20 discovery,
17 discovery,
21 encoding,
18 encoding,
22 error,
19 error,
@@ -463,86 +460,6 b' def _capabilitiesv2(repo, proto):'
463
460
464 return proto.addcapabilities(repo, caps)
461 return proto.addcapabilities(repo, caps)
465
462
466 def builddeltarequests(store, nodes, haveparents):
467 """Build a series of revision delta requests against a backend store.
468
469 Returns a list of revision numbers in the order they should be sent
470 and a list of ``irevisiondeltarequest`` instances to be made against
471 the backend store.
472 """
473 # We sort and send nodes in DAG order because this is optimal for
474 # storage emission.
475 # TODO we may want a better storage API here - one where we can throw
476 # a list of nodes and delta preconditions over a figurative wall and
477 # have the storage backend figure it out for us.
478 revs = dagop.linearize({store.rev(n) for n in nodes}, store.parentrevs)
479
480 requests = []
481 seenrevs = set()
482
483 for rev in revs:
484 node = store.node(rev)
485 parentnodes = store.parents(node)
486 parentrevs = [store.rev(n) for n in parentnodes]
487 deltabaserev = store.deltaparent(rev)
488 deltabasenode = store.node(deltabaserev)
489
490 # The choice of whether to send a fulltext revision or a delta and
491 # what delta to send is governed by a few factors.
492 #
493 # To send a delta, we need to ensure the receiver is capable of
494 # decoding it. And that requires the receiver to have the base
495 # revision the delta is against.
496 #
497 # We can only guarantee the receiver has the base revision if
498 # a) we've already sent the revision as part of this group
499 # b) the receiver has indicated they already have the revision.
500 # And the mechanism for "b" is the client indicating they have
501 # parent revisions. So this means we can only send the delta if
502 # it is sent before or it is against a delta and the receiver says
503 # they have a parent.
504
505 # We can send storage delta if it is against a revision we've sent
506 # in this group.
507 if deltabaserev != nullrev and deltabaserev in seenrevs:
508 basenode = deltabasenode
509
510 # We can send storage delta if it is against a parent revision and
511 # the receiver indicates they have the parents.
512 elif (deltabaserev != nullrev and deltabaserev in parentrevs
513 and haveparents):
514 basenode = deltabasenode
515
516 # Otherwise the storage delta isn't appropriate. Fall back to
517 # using another delta, if possible.
518
519 # Use p1 if we've emitted it or receiver says they have it.
520 elif parentrevs[0] != nullrev and (
521 parentrevs[0] in seenrevs or haveparents):
522 basenode = parentnodes[0]
523
524 # Use p2 if we've emitted it or receiver says they have it.
525 elif parentrevs[1] != nullrev and (
526 parentrevs[1] in seenrevs or haveparents):
527 basenode = parentnodes[1]
528
529 # Nothing appropriate to delta against. Send the full revision.
530 else:
531 basenode = nullid
532
533 requests.append(changegroup.revisiondeltarequest(
534 node=node,
535 p1node=parentnodes[0],
536 p2node=parentnodes[1],
537 # Receiver deals with linknode resolution.
538 linknode=nullid,
539 basenode=basenode,
540 ))
541
542 seenrevs.add(rev)
543
544 return revs, requests
545
546 def wireprotocommand(name, args=None, permission='push'):
463 def wireprotocommand(name, args=None, permission='push'):
547 """Decorator to declare a wire protocol command.
464 """Decorator to declare a wire protocol command.
548
465
@@ -860,47 +777,33 b' def filedata(repo, proto, haveparents, n'
860 raise error.WireprotoCommandError('unknown file node: %s',
777 raise error.WireprotoCommandError('unknown file node: %s',
861 (hex(node),))
778 (hex(node),))
862
779
863 revs, requests = builddeltarequests(store, nodes, haveparents)
780 revisions = store.emitrevisions(nodes,
781 revisiondata=b'revision' in fields,
782 assumehaveparentrevisions=haveparents)
864
783
865 yield {
784 yield {
866 b'totalitems': len(revs),
785 b'totalitems': len(nodes),
867 }
786 }
868
787
869 if b'revision' in fields:
788 for revision in revisions:
870 deltas = store.emitrevisiondeltas(requests)
871 else:
872 deltas = None
873
874 for rev in revs:
875 node = store.node(rev)
876
877 if deltas is not None:
878 delta = next(deltas)
879 else:
880 delta = None
881
882 d = {
789 d = {
883 b'node': node,
790 b'node': revision.node,
884 }
791 }
885
792
886 if b'parents' in fields:
793 if b'parents' in fields:
887 d[b'parents'] = store.parents(node)
794 d[b'parents'] = [revision.p1node, revision.p2node]
888
795
889 followingmeta = []
796 followingmeta = []
890 followingdata = []
797 followingdata = []
891
798
892 if b'revision' in fields:
799 if b'revision' in fields:
893 assert delta is not None
800 if revision.revision is not None:
894 assert delta.flags == 0
801 followingmeta.append((b'revision', len(revision.revision)))
895 assert d[b'node'] == delta.node
802 followingdata.append(revision.revision)
896
897 if delta.revision is not None:
898 followingmeta.append((b'revision', len(delta.revision)))
899 followingdata.append(delta.revision)
900 else:
803 else:
901 d[b'deltabasenode'] = delta.basenode
804 d[b'deltabasenode'] = revision.basenode
902 followingmeta.append((b'delta', len(delta.delta)))
805 followingmeta.append((b'delta', len(revision.delta)))
903 followingdata.append(delta.delta)
806 followingdata.append(revision.delta)
904
807
905 if followingmeta:
808 if followingmeta:
906 d[b'fieldsfollowing'] = followingmeta
809 d[b'fieldsfollowing'] = followingmeta
@@ -910,13 +813,6 b' def filedata(repo, proto, haveparents, n'
910 for extra in followingdata:
813 for extra in followingdata:
911 yield extra
814 yield extra
912
815
913 if deltas is not None:
914 try:
915 next(deltas)
916 raise error.ProgrammingError('should not have more deltas')
917 except GeneratorExit:
918 pass
919
920 @wireprotocommand(
816 @wireprotocommand(
921 'heads',
817 'heads',
922 args={
818 args={
@@ -1019,47 +915,33 b' def manifestdata(repo, proto, haveparent'
1019 raise error.WireprotoCommandError(
915 raise error.WireprotoCommandError(
1020 'unknown node: %s', (node,))
916 'unknown node: %s', (node,))
1021
917
1022 revs, requests = builddeltarequests(store, nodes, haveparents)
918 revisions = store.emitrevisions(nodes,
919 revisiondata=b'revision' in fields,
920 assumehaveparentrevisions=haveparents)
1023
921
1024 yield {
922 yield {
1025 b'totalitems': len(revs),
923 b'totalitems': len(nodes),
1026 }
924 }
1027
925
1028 if b'revision' in fields:
926 for revision in revisions:
1029 deltas = store.emitrevisiondeltas(requests)
1030 else:
1031 deltas = None
1032
1033 for rev in revs:
1034 node = store.node(rev)
1035
1036 if deltas is not None:
1037 delta = next(deltas)
1038 else:
1039 delta = None
1040
1041 d = {
927 d = {
1042 b'node': node,
928 b'node': revision.node,
1043 }
929 }
1044
930
1045 if b'parents' in fields:
931 if b'parents' in fields:
1046 d[b'parents'] = store.parents(node)
932 d[b'parents'] = [revision.p1node, revision.p2node]
1047
933
1048 followingmeta = []
934 followingmeta = []
1049 followingdata = []
935 followingdata = []
1050
936
1051 if b'revision' in fields:
937 if b'revision' in fields:
1052 assert delta is not None
938 if revision.revision is not None:
1053 assert delta.flags == 0
939 followingmeta.append((b'revision', len(revision.revision)))
1054 assert d[b'node'] == delta.node
940 followingdata.append(revision.revision)
1055
1056 if delta.revision is not None:
1057 followingmeta.append((b'revision', len(delta.revision)))
1058 followingdata.append(delta.revision)
1059 else:
941 else:
1060 d[b'deltabasenode'] = delta.basenode
942 d[b'deltabasenode'] = revision.basenode
1061 followingmeta.append((b'delta', len(delta.delta)))
943 followingmeta.append((b'delta', len(revision.delta)))
1062 followingdata.append(delta.delta)
944 followingdata.append(revision.delta)
1063
945
1064 if followingmeta:
946 if followingmeta:
1065 d[b'fieldsfollowing'] = followingmeta
947 d[b'fieldsfollowing'] = followingmeta
@@ -1069,13 +951,6 b' def manifestdata(repo, proto, haveparent'
1069 for extra in followingdata:
951 for extra in followingdata:
1070 yield extra
952 yield extra
1071
953
1072 if deltas is not None:
1073 try:
1074 next(deltas)
1075 raise error.ProgrammingError('should not have more deltas')
1076 except GeneratorExit:
1077 pass
1078
1079 @wireprotocommand(
954 @wireprotocommand(
1080 'pushkey',
955 'pushkey',
1081 args={
956 args={
General Comments 0
You need to be logged in to leave comments. Login now