hgext/narrow/narrowwirepeer.py
changeset 40070 8feae5b989bc
parent 39934 a24f4638d6c1
child 40071 e8132a8897da
--- a/hgext/narrow/narrowwirepeer.py	Fri Oct 05 21:43:57 2018 +0900
+++ b/hgext/narrow/narrowwirepeer.py	Fri Sep 28 23:42:31 2018 +0300
@@ -8,14 +8,24 @@
 from __future__ import absolute_import
 
 from mercurial import (
+    bundle2,
+    error,
     extensions,
     hg,
+    match as matchmod,
+    narrowspec,
+    pycompat,
     wireprotoserver,
+    wireprototypes,
+    wireprotov1peer,
     wireprotov1server,
 )
 
+from . import narrowbundle2
+
 def uisetup():
     extensions.wrapfunction(wireprotov1server, '_capabilities', addnarrowcap)
+    wireprotov1peer.wirepeer.narrow_widen = peernarrowwiden
 
 def addnarrowcap(orig, repo, proto):
     """add the narrow capability to the server"""
@@ -37,3 +47,78 @@
             return orig(cmd, *args, **kwargs)
         extensions.wrapfunction(peer, '_calltwowaystream', wrapped)
     hg.wirepeersetupfuncs.append(wirereposetup)
+
+@wireprotov1server.wireprotocommand('narrow_widen', 'oldincludes oldexcludes'
+                                                    ' newincludes newexcludes'
+                                                    ' commonheads cgversion'
+                                                    ' known ellipses',
+                                    permission='pull')
+def narrow_widen(repo, proto, oldincludes, oldexcludes, newincludes,
+                 newexcludes, commonheads, cgversion, known, ellipses):
+    """wireprotocol command to send data when a narrow clone is widen. We will
+    be sending a changegroup here.
+
+    The current set of arguments which are required:
+    oldincludes: the old includes of the narrow copy
+    oldexcludes: the old excludes of the narrow copy
+    newincludes: the new includes of the narrow copy
+    newexcludes: the new excludes of the narrow copy
+    commonheads: list of heads which are common between the server and client
+    cgversion(maybe): the changegroup version to produce
+    known: list of nodes which are known on the client (used in ellipses cases)
+    ellipses: whether to send ellipses data or not
+    """
+
+    bundler = bundle2.bundle20(repo.ui)
+    try:
+        oldincludes = wireprototypes.decodelist(oldincludes)
+        newincludes = wireprototypes.decodelist(newincludes)
+        oldexcludes = wireprototypes.decodelist(oldexcludes)
+        newexcludes = wireprototypes.decodelist(newexcludes)
+        # validate the patterns
+        narrowspec.validatepatterns(set(oldincludes))
+        narrowspec.validatepatterns(set(newincludes))
+        narrowspec.validatepatterns(set(oldexcludes))
+        narrowspec.validatepatterns(set(newexcludes))
+
+        common = wireprototypes.decodelist(commonheads)
+        known = None
+        if known:
+            known = wireprototypes.decodelist(known)
+        if ellipses == '0':
+            ellipses = False
+        else:
+            ellipses = bool(ellipses)
+        cgversion = cgversion
+        newmatch = narrowspec.match(repo.root, include=newincludes,
+                                    exclude=newexcludes)
+        oldmatch = narrowspec.match(repo.root, include=oldincludes,
+                                    exclude=oldexcludes)
+        diffmatch = matchmod.differencematcher(newmatch, oldmatch)
+
+        # get changegroup data
+        cg = narrowbundle2.widen_bundle(repo, diffmatch, common, known,
+                                        cgversion, ellipses)
+        if cg is not None:
+            part = bundler.newpart('changegroup', data=cg)
+            part.addparam('version', cgversion)
+            if 'treemanifest' in repo.requirements:
+                part.addparam('treemanifest', '1')
+    except error.Abort as exc:
+        manargs = [('message', pycompat.bytestr(exc))]
+        advargs = []
+        if exc.hint is not None:
+            advargs.append(('hint', exc.hint))
+        bundler.addpart(bundle2.bundlepart('error:abort', manargs, advargs))
+
+    chunks = bundler.getchunks()
+    return wireprototypes.streamres(gen=chunks)
+
+def peernarrowwiden(remote, **kwargs):
+    for ch in ('oldincludes', 'newincludes', 'oldexcludes', 'newexcludes',
+               'commonheads', 'known'):
+        kwargs[ch] = wireprototypes.encodelist(kwargs[ch])
+
+    kwargs['ellipses'] = '%i' % bool(kwargs['ellipses'])
+    f = remote._callcompressable('narrow_widen', **kwargs)
+    return bundle2.getunbundler(remote.ui, f)