Show More
@@ -12,11 +12,8 b' from .i18n import _' | |||
|
12 | 12 | from .node import ( |
|
13 | 13 | hex, |
|
14 | 14 | nullid, |
|
15 | nullrev, | |
|
16 | 15 | ) |
|
17 | 16 | from . import ( |
|
18 | changegroup, | |
|
19 | dagop, | |
|
20 | 17 | discovery, |
|
21 | 18 | encoding, |
|
22 | 19 | error, |
@@ -463,86 +460,6 b' def _capabilitiesv2(repo, proto):' | |||
|
463 | 460 | |
|
464 | 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 | 463 | def wireprotocommand(name, args=None, permission='push'): |
|
547 | 464 | """Decorator to declare a wire protocol command. |
|
548 | 465 | |
@@ -860,47 +777,33 b' def filedata(repo, proto, haveparents, n' | |||
|
860 | 777 | raise error.WireprotoCommandError('unknown file node: %s', |
|
861 | 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 | 784 | yield { |
|
866 |
b'totalitems': len( |
|
|
785 | b'totalitems': len(nodes), | |
|
867 | 786 | } |
|
868 | 787 | |
|
869 |
|
|
|
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 | ||
|
788 | for revision in revisions: | |
|
882 | 789 | d = { |
|
883 | b'node': node, | |
|
790 | b'node': revision.node, | |
|
884 | 791 | } |
|
885 | 792 | |
|
886 | 793 | if b'parents' in fields: |
|
887 |
d[b'parents'] = |
|
|
794 | d[b'parents'] = [revision.p1node, revision.p2node] | |
|
888 | 795 | |
|
889 | 796 | followingmeta = [] |
|
890 | 797 | followingdata = [] |
|
891 | 798 | |
|
892 | 799 | if b'revision' in fields: |
|
893 |
|
|
|
894 | assert delta.flags == 0 | |
|
895 | assert d[b'node'] == delta.node | |
|
896 | ||
|
897 | if delta.revision is not None: | |
|
898 | followingmeta.append((b'revision', len(delta.revision))) | |
|
899 | followingdata.append(delta.revision) | |
|
800 | if revision.revision is not None: | |
|
801 | followingmeta.append((b'revision', len(revision.revision))) | |
|
802 | followingdata.append(revision.revision) | |
|
900 | 803 | else: |
|
901 |
d[b'deltabasenode'] = |
|
|
902 |
followingmeta.append((b'delta', len( |
|
|
903 |
followingdata.append( |
|
|
804 | d[b'deltabasenode'] = revision.basenode | |
|
805 | followingmeta.append((b'delta', len(revision.delta))) | |
|
806 | followingdata.append(revision.delta) | |
|
904 | 807 | |
|
905 | 808 | if followingmeta: |
|
906 | 809 | d[b'fieldsfollowing'] = followingmeta |
@@ -910,13 +813,6 b' def filedata(repo, proto, haveparents, n' | |||
|
910 | 813 | for extra in followingdata: |
|
911 | 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 | 816 | @wireprotocommand( |
|
921 | 817 | 'heads', |
|
922 | 818 | args={ |
@@ -1019,47 +915,33 b' def manifestdata(repo, proto, haveparent' | |||
|
1019 | 915 | raise error.WireprotoCommandError( |
|
1020 | 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 | 922 | yield { |
|
1025 |
b'totalitems': len( |
|
|
923 | b'totalitems': len(nodes), | |
|
1026 | 924 | } |
|
1027 | 925 | |
|
1028 |
|
|
|
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 | ||
|
926 | for revision in revisions: | |
|
1041 | 927 | d = { |
|
1042 | b'node': node, | |
|
928 | b'node': revision.node, | |
|
1043 | 929 | } |
|
1044 | 930 | |
|
1045 | 931 | if b'parents' in fields: |
|
1046 |
d[b'parents'] = |
|
|
932 | d[b'parents'] = [revision.p1node, revision.p2node] | |
|
1047 | 933 | |
|
1048 | 934 | followingmeta = [] |
|
1049 | 935 | followingdata = [] |
|
1050 | 936 | |
|
1051 | 937 | if b'revision' in fields: |
|
1052 |
|
|
|
1053 | assert delta.flags == 0 | |
|
1054 | assert d[b'node'] == delta.node | |
|
1055 | ||
|
1056 | if delta.revision is not None: | |
|
1057 | followingmeta.append((b'revision', len(delta.revision))) | |
|
1058 | followingdata.append(delta.revision) | |
|
938 | if revision.revision is not None: | |
|
939 | followingmeta.append((b'revision', len(revision.revision))) | |
|
940 | followingdata.append(revision.revision) | |
|
1059 | 941 | else: |
|
1060 |
d[b'deltabasenode'] = |
|
|
1061 |
followingmeta.append((b'delta', len( |
|
|
1062 |
followingdata.append( |
|
|
942 | d[b'deltabasenode'] = revision.basenode | |
|
943 | followingmeta.append((b'delta', len(revision.delta))) | |
|
944 | followingdata.append(revision.delta) | |
|
1063 | 945 | |
|
1064 | 946 | if followingmeta: |
|
1065 | 947 | d[b'fieldsfollowing'] = followingmeta |
@@ -1069,13 +951,6 b' def manifestdata(repo, proto, haveparent' | |||
|
1069 | 951 | for extra in followingdata: |
|
1070 | 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 | 954 | @wireprotocommand( |
|
1080 | 955 | 'pushkey', |
|
1081 | 956 | args={ |
General Comments 0
You need to be logged in to leave comments.
Login now