##// END OF EJS Templates
changegroup: refactor delta parent code...
Gregory Szorc -
r39053:ef3d3a2f default
parent child Browse files
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, deltaparentfn):
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, deltaparentfn,
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 deltaparentfn)
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 deltaparentfn)
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 deltaparentfn, builddeltaheader, manifestsend,
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 deltaparentfn is a callable that resolves the delta parent for
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._deltaparentfn = deltaparentfn
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._deltaparentfn,
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._deltaparentfn,
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._deltaparentfn,
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