586 linknode=linknode, |
586 linknode=linknode, |
587 flags=store.flags(rev), |
587 flags=store.flags(rev), |
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, |
594 bundlecaps=None, ellipses=False, |
688 bundlecaps=None, ellipses=False, |
595 shallow=False, ellipsisroots=None, fullnodes=None): |
689 shallow=False, ellipsisroots=None, fullnodes=None): |
705 delta = _revisiondeltanormal(store, curr, prev, linknode, |
799 delta = _revisiondeltanormal(store, curr, prev, linknode, |
706 self._deltaparentfn) |
800 self._deltaparentfn) |
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 = self._revisiondeltanarrow( |
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) |
714 else: |
808 else: |
715 delta = _revisiondeltanormal(store, curr, prev, linknode, |
809 delta = _revisiondeltanormal(store, curr, prev, linknode, |
1055 clrevtolocalrev=clrevtolocalrev): |
1149 clrevtolocalrev=clrevtolocalrev): |
1056 size += len(chunk) |
1150 size += len(chunk) |
1057 yield chunk |
1151 yield chunk |
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 |
|
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 |
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 |
1158 Used for version 1 changegroups, which don't support generaldelta. |
1158 Used for version 1 changegroups, which don't support generaldelta. |