--- a/hgext/narrow/narrowbundle2.py Fri Oct 11 22:02:44 2019 -0700
+++ b/hgext/narrow/narrowbundle2.py Thu Oct 10 22:18:35 2019 -0700
@@ -184,6 +184,105 @@
part.addparam(b'treemanifest', b'1')
+def generate_ellipses_bundle2_for_widening(
+ bundler,
+ repo,
+ oldinclude,
+ oldexclude,
+ newinclude,
+ newexclude,
+ version,
+ common,
+ heads,
+ known,
+ depth,
+):
+ newmatch = narrowspec.match(
+ repo.root, include=newinclude, exclude=newexclude
+ )
+ if depth is not None:
+ depth = int(depth)
+ if depth < 1:
+ raise error.Abort(_(b'depth must be positive, got %d') % depth)
+
+ heads = set(heads or repo.heads())
+ common = set(common or [nullid])
+ if known and (oldinclude != newinclude or oldexclude != newexclude):
+ # Steps:
+ # 1. Send kill for "$known & ::common"
+ #
+ # 2. Send changegroup for ::common
+ #
+ # 3. Proceed.
+ #
+ # In the future, we can send kills for only the specific
+ # nodes we know should go away or change shape, and then
+ # send a data stream that tells the client something like this:
+ #
+ # a) apply this changegroup
+ # b) apply nodes XXX, YYY, ZZZ that you already have
+ # c) goto a
+ #
+ # until they've built up the full new state.
+ # Convert to revnums and intersect with "common". The client should
+ # have made it a subset of "common" already, but let's be safe.
+ known = set(repo.revs(b"%ln & ::%ln", known, common))
+ # TODO: we could send only roots() of this set, and the
+ # list of nodes in common, and the client could work out
+ # what to strip, instead of us explicitly sending every
+ # single node.
+ deadrevs = known
+
+ def genkills():
+ for r in deadrevs:
+ yield _KILLNODESIGNAL
+ yield repo.changelog.node(r)
+ yield _DONESIGNAL
+
+ bundler.newpart(_CHANGESPECPART, data=genkills())
+ newvisit, newfull, newellipsis = exchange._computeellipsis(
+ repo, set(), common, known, newmatch
+ )
+ if newvisit:
+ packer = changegroup.getbundler(
+ version,
+ repo,
+ matcher=newmatch,
+ ellipses=True,
+ shallow=depth is not None,
+ ellipsisroots=newellipsis,
+ fullnodes=newfull,
+ )
+ cgdata = packer.generate(common, newvisit, False, b'narrow_widen')
+
+ part = bundler.newpart(b'changegroup', data=cgdata)
+ part.addparam(b'version', version)
+ if b'treemanifest' in repo.requirements:
+ part.addparam(b'treemanifest', b'1')
+
+ visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
+ repo, common, heads, set(), newmatch, depth=depth
+ )
+
+ repo.ui.debug(b'Found %d relevant revs\n' % len(relevant_nodes))
+ if visitnodes:
+ packer = changegroup.getbundler(
+ version,
+ repo,
+ matcher=newmatch,
+ ellipses=True,
+ shallow=depth is not None,
+ ellipsisroots=ellipsisroots,
+ fullnodes=relevant_nodes,
+ )
+ cgdata = packer.generate(common, visitnodes, False, b'narrow_widen')
+
+ part = bundler.newpart(b'changegroup', data=cgdata)
+ part.addparam(b'version', version)
+ if b'treemanifest' in repo.requirements:
+ part.addparam(b'treemanifest', b'1')
+
+
@bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
def _handlechangespec_2(op, inpart):
# XXX: This bundle2 handling is buggy and should be removed after hg5.2 is