--- a/mercurial/wireprotov1peer.py Wed Apr 11 12:49:08 2018 -0700
+++ b/mercurial/wireprotov1peer.py Wed Apr 11 12:51:09 2018 -0700
@@ -19,7 +19,6 @@
changegroup as changegroupmod,
encoding,
error,
- peer,
pushkey as pushkeymod,
pycompat,
repository,
@@ -29,7 +28,76 @@
urlreq = util.urlreq
-class remoteiterbatcher(peer.iterbatcher):
+def batchable(f):
+ '''annotation for batchable methods
+
+ Such methods must implement a coroutine as follows:
+
+ @batchable
+ def sample(self, one, two=None):
+ # Build list of encoded arguments suitable for your wire protocol:
+ encargs = [('one', encode(one),), ('two', encode(two),)]
+ # Create future for injection of encoded result:
+ encresref = future()
+ # Return encoded arguments and future:
+ yield encargs, encresref
+ # Assuming the future to be filled with the result from the batched
+ # request now. Decode it:
+ yield decode(encresref.value)
+
+ The decorator returns a function which wraps this coroutine as a plain
+ method, but adds the original method as an attribute called "batchable",
+ which is used by remotebatch to split the call into separate encoding and
+ decoding phases.
+ '''
+ def plain(*args, **opts):
+ batchable = f(*args, **opts)
+ encargsorres, encresref = next(batchable)
+ if not encresref:
+ return encargsorres # a local result in this case
+ self = args[0]
+ cmd = pycompat.bytesurl(f.__name__) # ensure cmd is ascii bytestr
+ encresref.set(self._submitone(cmd, encargsorres))
+ return next(batchable)
+ setattr(plain, 'batchable', f)
+ return plain
+
+class future(object):
+ '''placeholder for a value to be set later'''
+ def set(self, value):
+ if util.safehasattr(self, 'value'):
+ raise error.RepoError("future is already set")
+ self.value = value
+
+class batcher(object):
+ '''base class for batches of commands submittable in a single request
+
+ All methods invoked on instances of this class are simply queued and
+ return a a future for the result. Once you call submit(), all the queued
+ calls are performed and the results set in their respective futures.
+ '''
+ def __init__(self):
+ self.calls = []
+ def __getattr__(self, name):
+ def call(*args, **opts):
+ resref = future()
+ # Please don't invent non-ascii method names, or you will
+ # give core hg a very sad time.
+ self.calls.append((name.encode('ascii'), args, opts, resref,))
+ return resref
+ return call
+ def submit(self):
+ raise NotImplementedError()
+
+class iterbatcher(batcher):
+
+ def submit(self):
+ raise NotImplementedError()
+
+ def results(self):
+ raise NotImplementedError()
+
+class remoteiterbatcher(iterbatcher):
def __init__(self, remote):
super(remoteiterbatcher, self).__init__()
self._remote = remote
@@ -92,11 +160,6 @@
yield finalfuture.value
-# Forward a couple of names from peer to make wireproto interactions
-# slightly more sensible.
-batchable = peer.batchable
-future = peer.future
-
def encodebatchcmds(req):
"""Return a ``cmds`` argument value for the ``batch`` command."""
escapearg = wireprototypes.escapebatcharg