Show More
@@ -588,6 +588,100 b' def _revisiondeltanormal(store, rev, pre' | |||||
588 | deltachunks=(prefix, delta), |
|
588 | deltachunks=(prefix, delta), | |
589 | ) |
|
589 | ) | |
590 |
|
590 | |||
|
591 | def _revisiondeltanarrow(cl, store, ischangelog, rev, linkrev, | |||
|
592 | linknode, clrevtolocalrev, fullclnodes, | |||
|
593 | precomputedellipsis): | |||
|
594 | linkparents = precomputedellipsis[linkrev] | |||
|
595 | def local(clrev): | |||
|
596 | """Turn a changelog revnum into a local revnum. | |||
|
597 | ||||
|
598 | The ellipsis dag is stored as revnums on the changelog, | |||
|
599 | but when we're producing ellipsis entries for | |||
|
600 | non-changelog revlogs, we need to turn those numbers into | |||
|
601 | something local. This does that for us, and during the | |||
|
602 | changelog sending phase will also expand the stored | |||
|
603 | mappings as needed. | |||
|
604 | """ | |||
|
605 | if clrev == nullrev: | |||
|
606 | return nullrev | |||
|
607 | ||||
|
608 | if ischangelog: | |||
|
609 | return clrev | |||
|
610 | ||||
|
611 | # Walk the ellipsis-ized changelog breadth-first looking for a | |||
|
612 | # change that has been linked from the current revlog. | |||
|
613 | # | |||
|
614 | # For a flat manifest revlog only a single step should be necessary | |||
|
615 | # as all relevant changelog entries are relevant to the flat | |||
|
616 | # manifest. | |||
|
617 | # | |||
|
618 | # For a filelog or tree manifest dirlog however not every changelog | |||
|
619 | # entry will have been relevant, so we need to skip some changelog | |||
|
620 | # nodes even after ellipsis-izing. | |||
|
621 | walk = [clrev] | |||
|
622 | while walk: | |||
|
623 | p = walk[0] | |||
|
624 | walk = walk[1:] | |||
|
625 | if p in clrevtolocalrev: | |||
|
626 | return clrevtolocalrev[p] | |||
|
627 | elif p in fullclnodes: | |||
|
628 | walk.extend([pp for pp in cl.parentrevs(p) | |||
|
629 | if pp != nullrev]) | |||
|
630 | elif p in precomputedellipsis: | |||
|
631 | walk.extend([pp for pp in precomputedellipsis[p] | |||
|
632 | if pp != nullrev]) | |||
|
633 | else: | |||
|
634 | # In this case, we've got an ellipsis with parents | |||
|
635 | # outside the current bundle (likely an | |||
|
636 | # incremental pull). We "know" that we can use the | |||
|
637 | # value of this same revlog at whatever revision | |||
|
638 | # is pointed to by linknode. "Know" is in scare | |||
|
639 | # quotes because I haven't done enough examination | |||
|
640 | # of edge cases to convince myself this is really | |||
|
641 | # a fact - it works for all the (admittedly | |||
|
642 | # thorough) cases in our testsuite, but I would be | |||
|
643 | # somewhat unsurprised to find a case in the wild | |||
|
644 | # where this breaks down a bit. That said, I don't | |||
|
645 | # know if it would hurt anything. | |||
|
646 | for i in pycompat.xrange(rev, 0, -1): | |||
|
647 | if store.linkrev(i) == clrev: | |||
|
648 | return i | |||
|
649 | # We failed to resolve a parent for this node, so | |||
|
650 | # we crash the changegroup construction. | |||
|
651 | raise error.Abort( | |||
|
652 | 'unable to resolve parent while packing %r %r' | |||
|
653 | ' for changeset %r' % (store.indexfile, rev, clrev)) | |||
|
654 | ||||
|
655 | return nullrev | |||
|
656 | ||||
|
657 | if not linkparents or ( | |||
|
658 | store.parentrevs(rev) == (nullrev, nullrev)): | |||
|
659 | p1, p2 = nullrev, nullrev | |||
|
660 | elif len(linkparents) == 1: | |||
|
661 | p1, = sorted(local(p) for p in linkparents) | |||
|
662 | p2 = nullrev | |||
|
663 | else: | |||
|
664 | p1, p2 = sorted(local(p) for p in linkparents) | |||
|
665 | ||||
|
666 | n = store.node(rev) | |||
|
667 | p1n, p2n = store.node(p1), store.node(p2) | |||
|
668 | flags = store.flags(rev) | |||
|
669 | flags |= revlog.REVIDX_ELLIPSIS | |||
|
670 | ||||
|
671 | # TODO: try and actually send deltas for ellipsis data blocks | |||
|
672 | data = store.revision(n) | |||
|
673 | diffheader = mdiff.trivialdiffheader(len(data)) | |||
|
674 | ||||
|
675 | return revisiondelta( | |||
|
676 | node=n, | |||
|
677 | p1node=p1n, | |||
|
678 | p2node=p2n, | |||
|
679 | basenode=nullid, | |||
|
680 | linknode=linknode, | |||
|
681 | flags=flags, | |||
|
682 | deltachunks=(diffheader, data), | |||
|
683 | ) | |||
|
684 | ||||
591 | class cgpacker(object): |
|
685 | class cgpacker(object): | |
592 | def __init__(self, repo, filematcher, version, allowreorder, |
|
686 | def __init__(self, repo, filematcher, version, allowreorder, | |
593 | deltaparentfn, builddeltaheader, manifestsend, |
|
687 | deltaparentfn, builddeltaheader, manifestsend, | |
@@ -707,7 +801,7 b' class cgpacker(object):' | |||||
707 | elif linkrev not in self._precomputedellipsis: |
|
801 | elif linkrev not in self._precomputedellipsis: | |
708 | delta = None |
|
802 | delta = None | |
709 | else: |
|
803 | else: | |
710 |
delta = |
|
804 | delta = _revisiondeltanarrow( | |
711 | cl, store, ischangelog, curr, linkrev, linknode, |
|
805 | cl, store, ischangelog, curr, linkrev, linknode, | |
712 | clrevtolocalrev, self._fullclnodes, |
|
806 | clrevtolocalrev, self._fullclnodes, | |
713 | self._precomputedellipsis) |
|
807 | self._precomputedellipsis) | |
@@ -1058,100 +1152,6 b' class cgpacker(object):' | |||||
1058 | self._verbosenote(_('%8.i %s\n') % (size, fname)) |
|
1152 | self._verbosenote(_('%8.i %s\n') % (size, fname)) | |
1059 | progress.complete() |
|
1153 | progress.complete() | |
1060 |
|
1154 | |||
1061 | def _revisiondeltanarrow(self, cl, store, ischangelog, rev, linkrev, |
|
|||
1062 | linknode, clrevtolocalrev, fullclnodes, |
|
|||
1063 | precomputedellipsis): |
|
|||
1064 | linkparents = precomputedellipsis[linkrev] |
|
|||
1065 | def local(clrev): |
|
|||
1066 | """Turn a changelog revnum into a local revnum. |
|
|||
1067 |
|
||||
1068 | The ellipsis dag is stored as revnums on the changelog, |
|
|||
1069 | but when we're producing ellipsis entries for |
|
|||
1070 | non-changelog revlogs, we need to turn those numbers into |
|
|||
1071 | something local. This does that for us, and during the |
|
|||
1072 | changelog sending phase will also expand the stored |
|
|||
1073 | mappings as needed. |
|
|||
1074 | """ |
|
|||
1075 | if clrev == nullrev: |
|
|||
1076 | return nullrev |
|
|||
1077 |
|
||||
1078 | if ischangelog: |
|
|||
1079 | return clrev |
|
|||
1080 |
|
||||
1081 | # Walk the ellipsis-ized changelog breadth-first looking for a |
|
|||
1082 | # change that has been linked from the current revlog. |
|
|||
1083 | # |
|
|||
1084 | # For a flat manifest revlog only a single step should be necessary |
|
|||
1085 | # as all relevant changelog entries are relevant to the flat |
|
|||
1086 | # manifest. |
|
|||
1087 | # |
|
|||
1088 | # For a filelog or tree manifest dirlog however not every changelog |
|
|||
1089 | # entry will have been relevant, so we need to skip some changelog |
|
|||
1090 | # nodes even after ellipsis-izing. |
|
|||
1091 | walk = [clrev] |
|
|||
1092 | while walk: |
|
|||
1093 | p = walk[0] |
|
|||
1094 | walk = walk[1:] |
|
|||
1095 | if p in clrevtolocalrev: |
|
|||
1096 | return clrevtolocalrev[p] |
|
|||
1097 | elif p in fullclnodes: |
|
|||
1098 | walk.extend([pp for pp in cl.parentrevs(p) |
|
|||
1099 | if pp != nullrev]) |
|
|||
1100 | elif p in precomputedellipsis: |
|
|||
1101 | walk.extend([pp for pp in precomputedellipsis[p] |
|
|||
1102 | if pp != nullrev]) |
|
|||
1103 | else: |
|
|||
1104 | # In this case, we've got an ellipsis with parents |
|
|||
1105 | # outside the current bundle (likely an |
|
|||
1106 | # incremental pull). We "know" that we can use the |
|
|||
1107 | # value of this same revlog at whatever revision |
|
|||
1108 | # is pointed to by linknode. "Know" is in scare |
|
|||
1109 | # quotes because I haven't done enough examination |
|
|||
1110 | # of edge cases to convince myself this is really |
|
|||
1111 | # a fact - it works for all the (admittedly |
|
|||
1112 | # thorough) cases in our testsuite, but I would be |
|
|||
1113 | # somewhat unsurprised to find a case in the wild |
|
|||
1114 | # where this breaks down a bit. That said, I don't |
|
|||
1115 | # know if it would hurt anything. |
|
|||
1116 | for i in pycompat.xrange(rev, 0, -1): |
|
|||
1117 | if store.linkrev(i) == clrev: |
|
|||
1118 | return i |
|
|||
1119 | # We failed to resolve a parent for this node, so |
|
|||
1120 | # we crash the changegroup construction. |
|
|||
1121 | raise error.Abort( |
|
|||
1122 | 'unable to resolve parent while packing %r %r' |
|
|||
1123 | ' for changeset %r' % (store.indexfile, rev, clrev)) |
|
|||
1124 |
|
||||
1125 | return nullrev |
|
|||
1126 |
|
||||
1127 | if not linkparents or ( |
|
|||
1128 | store.parentrevs(rev) == (nullrev, nullrev)): |
|
|||
1129 | p1, p2 = nullrev, nullrev |
|
|||
1130 | elif len(linkparents) == 1: |
|
|||
1131 | p1, = sorted(local(p) for p in linkparents) |
|
|||
1132 | p2 = nullrev |
|
|||
1133 | else: |
|
|||
1134 | p1, p2 = sorted(local(p) for p in linkparents) |
|
|||
1135 |
|
||||
1136 | n = store.node(rev) |
|
|||
1137 | p1n, p2n = store.node(p1), store.node(p2) |
|
|||
1138 | flags = store.flags(rev) |
|
|||
1139 | flags |= revlog.REVIDX_ELLIPSIS |
|
|||
1140 |
|
||||
1141 | # TODO: try and actually send deltas for ellipsis data blocks |
|
|||
1142 | data = store.revision(n) |
|
|||
1143 | diffheader = mdiff.trivialdiffheader(len(data)) |
|
|||
1144 |
|
||||
1145 | return revisiondelta( |
|
|||
1146 | node=n, |
|
|||
1147 | p1node=p1n, |
|
|||
1148 | p2node=p2n, |
|
|||
1149 | basenode=nullid, |
|
|||
1150 | linknode=linknode, |
|
|||
1151 | flags=flags, |
|
|||
1152 | deltachunks=(diffheader, data), |
|
|||
1153 | ) |
|
|||
1154 |
|
||||
1155 | def _deltaparentprev(store, rev, p1, p2, prev): |
|
1155 | def _deltaparentprev(store, rev, p1, p2, prev): | |
1156 | """Resolve a delta parent to the previous revision. |
|
1156 | """Resolve a delta parent to the previous revision. | |
1157 |
|
1157 |
General Comments 0
You need to be logged in to leave comments.
Login now