Show More
@@ -587,11 +587,37 b' def _sortnodesellipsis(store, nodes, cl,' | |||
|
587 | 587 | key = lambda n: cl.rev(lookup(n)) |
|
588 | 588 | return [store.rev(n) for n in sorted(nodes, key=key)] |
|
589 | 589 | |
|
590 |
def _revisiondeltanormal(store, rev, prev, linknode, deltaparent |
|
|
590 | def _revisiondeltanormal(store, rev, prev, linknode, forcedeltaparentprev): | |
|
591 | 591 | """Construct a revision delta for non-ellipses changegroup generation.""" |
|
592 | 592 | node = store.node(rev) |
|
593 | 593 | p1, p2 = store.parentrevs(rev) |
|
594 | base = deltaparentfn(store, rev, p1, p2, prev) | |
|
594 | ||
|
595 | if forcedeltaparentprev: | |
|
596 | base = prev | |
|
597 | else: | |
|
598 | dp = store.deltaparent(rev) | |
|
599 | ||
|
600 | if dp == nullrev and store.storedeltachains: | |
|
601 | # Avoid sending full revisions when delta parent is null. Pick prev | |
|
602 | # in that case. It's tempting to pick p1 in this case, as p1 will | |
|
603 | # be smaller in the common case. However, computing a delta against | |
|
604 | # p1 may require resolving the raw text of p1, which could be | |
|
605 | # expensive. The revlog caches should have prev cached, meaning | |
|
606 | # less CPU for changegroup generation. There is likely room to add | |
|
607 | # a flag and/or config option to control this behavior. | |
|
608 | base = prev | |
|
609 | elif dp == nullrev: | |
|
610 | # revlog is configured to use full snapshot for a reason, | |
|
611 | # stick to full snapshot. | |
|
612 | base = nullrev | |
|
613 | elif dp not in (p1, p2, prev): | |
|
614 | # Pick prev when we can't be sure remote has the base revision. | |
|
615 | base = prev | |
|
616 | else: | |
|
617 | base = dp | |
|
618 | ||
|
619 | if base != nullrev and not store.candelta(base, rev): | |
|
620 | base = nullrev | |
|
595 | 621 | |
|
596 | 622 | revision = None |
|
597 | 623 | delta = None |
@@ -719,7 +745,7 b' def _revisiondeltanarrow(cl, store, isch' | |||
|
719 | 745 | delta=None, |
|
720 | 746 | ) |
|
721 | 747 | |
|
722 |
def deltagroup(repo, revs, store, ischangelog, lookup, deltaparent |
|
|
748 | def deltagroup(repo, revs, store, ischangelog, lookup, forcedeltaparentprev, | |
|
723 | 749 | units=None, |
|
724 | 750 | ellipses=False, clrevtolocalrev=None, fullclnodes=None, |
|
725 | 751 | precomputedellipsis=None): |
@@ -761,7 +787,7 b' def deltagroup(repo, revs, store, ischan' | |||
|
761 | 787 | # corresponds to was a full changeset. |
|
762 | 788 | if linknode in fullclnodes: |
|
763 | 789 | delta = _revisiondeltanormal(store, curr, prev, linknode, |
|
764 |
deltaparent |
|
|
790 | forcedeltaparentprev) | |
|
765 | 791 | elif linkrev not in precomputedellipsis: |
|
766 | 792 | delta = None |
|
767 | 793 | else: |
@@ -771,7 +797,7 b' def deltagroup(repo, revs, store, ischan' | |||
|
771 | 797 | precomputedellipsis) |
|
772 | 798 | else: |
|
773 | 799 | delta = _revisiondeltanormal(store, curr, prev, linknode, |
|
774 |
deltaparent |
|
|
800 | forcedeltaparentprev) | |
|
775 | 801 | |
|
776 | 802 | if delta: |
|
777 | 803 | yield delta |
@@ -781,7 +807,8 b' def deltagroup(repo, revs, store, ischan' | |||
|
781 | 807 | |
|
782 | 808 | class cgpacker(object): |
|
783 | 809 | def __init__(self, repo, filematcher, version, allowreorder, |
|
784 |
|
|
|
810 | builddeltaheader, manifestsend, | |
|
811 | forcedeltaparentprev=False, | |
|
785 | 812 | bundlecaps=None, ellipses=False, |
|
786 | 813 | shallow=False, ellipsisroots=None, fullnodes=None): |
|
787 | 814 | """Given a source repo, construct a bundler. |
@@ -793,8 +820,9 b' class cgpacker(object):' | |||
|
793 | 820 | This value is used when ``bundle.reorder`` is ``auto`` or isn't |
|
794 | 821 | set. |
|
795 | 822 | |
|
796 |
deltaparent |
|
|
797 | a specific revision. | |
|
823 | forcedeltaparentprev indicates whether delta parents must be against | |
|
824 | the previous revision in a delta group. This should only be used for | |
|
825 | compatibility with changegroup version 1. | |
|
798 | 826 | |
|
799 | 827 | builddeltaheader is a callable that constructs the header for a group |
|
800 | 828 | delta. |
@@ -820,7 +848,7 b' class cgpacker(object):' | |||
|
820 | 848 | self._filematcher = filematcher |
|
821 | 849 | |
|
822 | 850 | self.version = version |
|
823 |
self._deltaparent |
|
|
851 | self._forcedeltaparentprev = forcedeltaparentprev | |
|
824 | 852 | self._builddeltaheader = builddeltaheader |
|
825 | 853 | self._manifestsend = manifestsend |
|
826 | 854 | self._ellipses = ellipses |
@@ -1025,7 +1053,7 b' class cgpacker(object):' | |||
|
1025 | 1053 | |
|
1026 | 1054 | gen = deltagroup( |
|
1027 | 1055 | self._repo, revs, cl, True, lookupcl, |
|
1028 |
self._deltaparent |
|
|
1056 | self._forcedeltaparentprev, | |
|
1029 | 1057 | ellipses=self._ellipses, |
|
1030 | 1058 | units=_('changesets'), |
|
1031 | 1059 | clrevtolocalrev={}, |
@@ -1114,7 +1142,7 b' class cgpacker(object):' | |||
|
1114 | 1142 | |
|
1115 | 1143 | deltas = deltagroup( |
|
1116 | 1144 | self._repo, revs, store, False, lookupfn, |
|
1117 |
self._deltaparent |
|
|
1145 | self._forcedeltaparentprev, | |
|
1118 | 1146 | ellipses=self._ellipses, |
|
1119 | 1147 | units=_('manifests'), |
|
1120 | 1148 | clrevtolocalrev=clrevtolocalrev, |
@@ -1206,7 +1234,7 b' class cgpacker(object):' | |||
|
1206 | 1234 | |
|
1207 | 1235 | deltas = deltagroup( |
|
1208 | 1236 | self._repo, revs, filerevlog, False, lookupfilelog, |
|
1209 |
self._deltaparent |
|
|
1237 | self._forcedeltaparentprev, | |
|
1210 | 1238 | ellipses=self._ellipses, |
|
1211 | 1239 | clrevtolocalrev=clrevtolocalrev, |
|
1212 | 1240 | fullclnodes=self._fullclnodes, |
@@ -1216,65 +1244,16 b' class cgpacker(object):' | |||
|
1216 | 1244 | |
|
1217 | 1245 | progress.complete() |
|
1218 | 1246 | |
|
1219 | def _deltaparentprev(store, rev, p1, p2, prev): | |
|
1220 | """Resolve a delta parent to the previous revision. | |
|
1221 | ||
|
1222 | Used for version 1 changegroups, which don't support generaldelta. | |
|
1223 | """ | |
|
1224 | return prev | |
|
1225 | ||
|
1226 | def _deltaparentgeneraldelta(store, rev, p1, p2, prev): | |
|
1227 | """Resolve a delta parent when general deltas are supported.""" | |
|
1228 | dp = store.deltaparent(rev) | |
|
1229 | if dp == nullrev and store.storedeltachains: | |
|
1230 | # Avoid sending full revisions when delta parent is null. Pick prev | |
|
1231 | # in that case. It's tempting to pick p1 in this case, as p1 will | |
|
1232 | # be smaller in the common case. However, computing a delta against | |
|
1233 | # p1 may require resolving the raw text of p1, which could be | |
|
1234 | # expensive. The revlog caches should have prev cached, meaning | |
|
1235 | # less CPU for changegroup generation. There is likely room to add | |
|
1236 | # a flag and/or config option to control this behavior. | |
|
1237 | base = prev | |
|
1238 | elif dp == nullrev: | |
|
1239 | # revlog is configured to use full snapshot for a reason, | |
|
1240 | # stick to full snapshot. | |
|
1241 | base = nullrev | |
|
1242 | elif dp not in (p1, p2, prev): | |
|
1243 | # Pick prev when we can't be sure remote has the base revision. | |
|
1244 | return prev | |
|
1245 | else: | |
|
1246 | base = dp | |
|
1247 | ||
|
1248 | if base != nullrev and not store.candelta(base, rev): | |
|
1249 | base = nullrev | |
|
1250 | ||
|
1251 | return base | |
|
1252 | ||
|
1253 | def _deltaparentellipses(store, rev, p1, p2, prev): | |
|
1254 | """Resolve a delta parent when in ellipses mode.""" | |
|
1255 | # TODO: send better deltas when in narrow mode. | |
|
1256 | # | |
|
1257 | # changegroup.group() loops over revisions to send, | |
|
1258 | # including revisions we'll skip. What this means is that | |
|
1259 | # `prev` will be a potentially useless delta base for all | |
|
1260 | # ellipsis nodes, as the client likely won't have it. In | |
|
1261 | # the future we should do bookkeeping about which nodes | |
|
1262 | # have been sent to the client, and try to be | |
|
1263 | # significantly smarter about delta bases. This is | |
|
1264 | # slightly tricky because this same code has to work for | |
|
1265 | # all revlogs, and we don't have the linkrev/linknode here. | |
|
1266 | return p1 | |
|
1267 | ||
|
1268 | 1247 | def _makecg1packer(repo, filematcher, bundlecaps, ellipses=False, |
|
1269 | 1248 | shallow=False, ellipsisroots=None, fullnodes=None): |
|
1270 | 1249 | builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack( |
|
1271 | 1250 | d.node, d.p1node, d.p2node, d.linknode) |
|
1272 | 1251 | |
|
1273 | 1252 | return cgpacker(repo, filematcher, b'01', |
|
1274 | deltaparentfn=_deltaparentprev, | |
|
1275 | 1253 | allowreorder=None, |
|
1276 | 1254 | builddeltaheader=builddeltaheader, |
|
1277 | 1255 | manifestsend=b'', |
|
1256 | forcedeltaparentprev=True, | |
|
1278 | 1257 | bundlecaps=bundlecaps, |
|
1279 | 1258 | ellipses=ellipses, |
|
1280 | 1259 | shallow=shallow, |
@@ -1290,7 +1269,6 b' def _makecg2packer(repo, filematcher, bu' | |||
|
1290 | 1269 | # generally doesn't help, so we disable it by default (treating |
|
1291 | 1270 | # bundle.reorder=auto just like bundle.reorder=False). |
|
1292 | 1271 | return cgpacker(repo, filematcher, b'02', |
|
1293 | deltaparentfn=_deltaparentgeneraldelta, | |
|
1294 | 1272 | allowreorder=False, |
|
1295 | 1273 | builddeltaheader=builddeltaheader, |
|
1296 | 1274 | manifestsend=b'', |
@@ -1305,11 +1283,7 b' def _makecg3packer(repo, filematcher, bu' | |||
|
1305 | 1283 | builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack( |
|
1306 | 1284 | d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags) |
|
1307 | 1285 | |
|
1308 | deltaparentfn = (_deltaparentellipses if ellipses | |
|
1309 | else _deltaparentgeneraldelta) | |
|
1310 | ||
|
1311 | 1286 | return cgpacker(repo, filematcher, b'03', |
|
1312 | deltaparentfn=deltaparentfn, | |
|
1313 | 1287 | allowreorder=False, |
|
1314 | 1288 | builddeltaheader=builddeltaheader, |
|
1315 | 1289 | manifestsend=closechunk(), |
General Comments 0
You need to be logged in to leave comments.
Login now