##// 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 key = lambda n: cl.rev(lookup(n))
587 key = lambda n: cl.rev(lookup(n))
588 return [store.rev(n) for n in sorted(nodes, key=key)]
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 """Construct a revision delta for non-ellipses changegroup generation."""
591 """Construct a revision delta for non-ellipses changegroup generation."""
592 node = store.node(rev)
592 node = store.node(rev)
593 p1, p2 = store.parentrevs(rev)
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 revision = None
622 revision = None
597 delta = None
623 delta = None
@@ -719,7 +745,7 b' def _revisiondeltanarrow(cl, store, isch'
719 delta=None,
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 units=None,
749 units=None,
724 ellipses=False, clrevtolocalrev=None, fullclnodes=None,
750 ellipses=False, clrevtolocalrev=None, fullclnodes=None,
725 precomputedellipsis=None):
751 precomputedellipsis=None):
@@ -761,7 +787,7 b' def deltagroup(repo, revs, store, ischan'
761 # corresponds to was a full changeset.
787 # corresponds to was a full changeset.
762 if linknode in fullclnodes:
788 if linknode in fullclnodes:
763 delta = _revisiondeltanormal(store, curr, prev, linknode,
789 delta = _revisiondeltanormal(store, curr, prev, linknode,
764 deltaparentfn)
790 forcedeltaparentprev)
765 elif linkrev not in precomputedellipsis:
791 elif linkrev not in precomputedellipsis:
766 delta = None
792 delta = None
767 else:
793 else:
@@ -771,7 +797,7 b' def deltagroup(repo, revs, store, ischan'
771 precomputedellipsis)
797 precomputedellipsis)
772 else:
798 else:
773 delta = _revisiondeltanormal(store, curr, prev, linknode,
799 delta = _revisiondeltanormal(store, curr, prev, linknode,
774 deltaparentfn)
800 forcedeltaparentprev)
775
801
776 if delta:
802 if delta:
777 yield delta
803 yield delta
@@ -781,7 +807,8 b' def deltagroup(repo, revs, store, ischan'
781
807
782 class cgpacker(object):
808 class cgpacker(object):
783 def __init__(self, repo, filematcher, version, allowreorder,
809 def __init__(self, repo, filematcher, version, allowreorder,
784 deltaparentfn, builddeltaheader, manifestsend,
810 builddeltaheader, manifestsend,
811 forcedeltaparentprev=False,
785 bundlecaps=None, ellipses=False,
812 bundlecaps=None, ellipses=False,
786 shallow=False, ellipsisroots=None, fullnodes=None):
813 shallow=False, ellipsisroots=None, fullnodes=None):
787 """Given a source repo, construct a bundler.
814 """Given a source repo, construct a bundler.
@@ -793,8 +820,9 b' class cgpacker(object):'
793 This value is used when ``bundle.reorder`` is ``auto`` or isn't
820 This value is used when ``bundle.reorder`` is ``auto`` or isn't
794 set.
821 set.
795
822
796 deltaparentfn is a callable that resolves the delta parent for
823 forcedeltaparentprev indicates whether delta parents must be against
797 a specific revision.
824 the previous revision in a delta group. This should only be used for
825 compatibility with changegroup version 1.
798
826
799 builddeltaheader is a callable that constructs the header for a group
827 builddeltaheader is a callable that constructs the header for a group
800 delta.
828 delta.
@@ -820,7 +848,7 b' class cgpacker(object):'
820 self._filematcher = filematcher
848 self._filematcher = filematcher
821
849
822 self.version = version
850 self.version = version
823 self._deltaparentfn = deltaparentfn
851 self._forcedeltaparentprev = forcedeltaparentprev
824 self._builddeltaheader = builddeltaheader
852 self._builddeltaheader = builddeltaheader
825 self._manifestsend = manifestsend
853 self._manifestsend = manifestsend
826 self._ellipses = ellipses
854 self._ellipses = ellipses
@@ -1025,7 +1053,7 b' class cgpacker(object):'
1025
1053
1026 gen = deltagroup(
1054 gen = deltagroup(
1027 self._repo, revs, cl, True, lookupcl,
1055 self._repo, revs, cl, True, lookupcl,
1028 self._deltaparentfn,
1056 self._forcedeltaparentprev,
1029 ellipses=self._ellipses,
1057 ellipses=self._ellipses,
1030 units=_('changesets'),
1058 units=_('changesets'),
1031 clrevtolocalrev={},
1059 clrevtolocalrev={},
@@ -1114,7 +1142,7 b' class cgpacker(object):'
1114
1142
1115 deltas = deltagroup(
1143 deltas = deltagroup(
1116 self._repo, revs, store, False, lookupfn,
1144 self._repo, revs, store, False, lookupfn,
1117 self._deltaparentfn,
1145 self._forcedeltaparentprev,
1118 ellipses=self._ellipses,
1146 ellipses=self._ellipses,
1119 units=_('manifests'),
1147 units=_('manifests'),
1120 clrevtolocalrev=clrevtolocalrev,
1148 clrevtolocalrev=clrevtolocalrev,
@@ -1206,7 +1234,7 b' class cgpacker(object):'
1206
1234
1207 deltas = deltagroup(
1235 deltas = deltagroup(
1208 self._repo, revs, filerevlog, False, lookupfilelog,
1236 self._repo, revs, filerevlog, False, lookupfilelog,
1209 self._deltaparentfn,
1237 self._forcedeltaparentprev,
1210 ellipses=self._ellipses,
1238 ellipses=self._ellipses,
1211 clrevtolocalrev=clrevtolocalrev,
1239 clrevtolocalrev=clrevtolocalrev,
1212 fullclnodes=self._fullclnodes,
1240 fullclnodes=self._fullclnodes,
@@ -1216,65 +1244,16 b' class cgpacker(object):'
1216
1244
1217 progress.complete()
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 def _makecg1packer(repo, filematcher, bundlecaps, ellipses=False,
1247 def _makecg1packer(repo, filematcher, bundlecaps, ellipses=False,
1269 shallow=False, ellipsisroots=None, fullnodes=None):
1248 shallow=False, ellipsisroots=None, fullnodes=None):
1270 builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack(
1249 builddeltaheader = lambda d: _CHANGEGROUPV1_DELTA_HEADER.pack(
1271 d.node, d.p1node, d.p2node, d.linknode)
1250 d.node, d.p1node, d.p2node, d.linknode)
1272
1251
1273 return cgpacker(repo, filematcher, b'01',
1252 return cgpacker(repo, filematcher, b'01',
1274 deltaparentfn=_deltaparentprev,
1275 allowreorder=None,
1253 allowreorder=None,
1276 builddeltaheader=builddeltaheader,
1254 builddeltaheader=builddeltaheader,
1277 manifestsend=b'',
1255 manifestsend=b'',
1256 forcedeltaparentprev=True,
1278 bundlecaps=bundlecaps,
1257 bundlecaps=bundlecaps,
1279 ellipses=ellipses,
1258 ellipses=ellipses,
1280 shallow=shallow,
1259 shallow=shallow,
@@ -1290,7 +1269,6 b' def _makecg2packer(repo, filematcher, bu'
1290 # generally doesn't help, so we disable it by default (treating
1269 # generally doesn't help, so we disable it by default (treating
1291 # bundle.reorder=auto just like bundle.reorder=False).
1270 # bundle.reorder=auto just like bundle.reorder=False).
1292 return cgpacker(repo, filematcher, b'02',
1271 return cgpacker(repo, filematcher, b'02',
1293 deltaparentfn=_deltaparentgeneraldelta,
1294 allowreorder=False,
1272 allowreorder=False,
1295 builddeltaheader=builddeltaheader,
1273 builddeltaheader=builddeltaheader,
1296 manifestsend=b'',
1274 manifestsend=b'',
@@ -1305,11 +1283,7 b' def _makecg3packer(repo, filematcher, bu'
1305 builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack(
1283 builddeltaheader = lambda d: _CHANGEGROUPV3_DELTA_HEADER.pack(
1306 d.node, d.p1node, d.p2node, d.basenode, d.linknode, d.flags)
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 return cgpacker(repo, filematcher, b'03',
1286 return cgpacker(repo, filematcher, b'03',
1312 deltaparentfn=deltaparentfn,
1313 allowreorder=False,
1287 allowreorder=False,
1314 builddeltaheader=builddeltaheader,
1288 builddeltaheader=builddeltaheader,
1315 manifestsend=closechunk(),
1289 manifestsend=closechunk(),
General Comments 0
You need to be logged in to leave comments. Login now