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( |
|
785 | b'totalitems': len(nodes), | |
867 | } |
|
786 | } | |
868 |
|
787 | |||
869 |
|
|
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'] = |
|
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 |
|
|
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'] = |
|
804 | d[b'deltabasenode'] = revision.basenode | |
902 |
followingmeta.append((b'delta', len( |
|
805 | followingmeta.append((b'delta', len(revision.delta))) | |
903 |
followingdata.append( |
|
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( |
|
923 | b'totalitems': len(nodes), | |
1026 | } |
|
924 | } | |
1027 |
|
925 | |||
1028 |
|
|
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'] = |
|
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 |
|
|
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'] = |
|
942 | d[b'deltabasenode'] = revision.basenode | |
1061 |
followingmeta.append((b'delta', len( |
|
943 | followingmeta.append((b'delta', len(revision.delta))) | |
1062 |
followingdata.append( |
|
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