2016-03-29 13:44:58 +03:00
|
|
|
from __future__ import absolute_import, print_function
|
2015-12-07 09:02:39 +03:00
|
|
|
|
2016-04-11 00:32:08 +03:00
|
|
|
from mercurial import (
|
2016-04-10 23:55:37 +03:00
|
|
|
util,
|
2016-04-11 00:32:08 +03:00
|
|
|
wireproto,
|
|
|
|
)
|
2016-04-10 23:55:37 +03:00
|
|
|
stringio = util.stringio
|
2011-06-15 00:52:58 +04:00
|
|
|
|
2011-06-29 17:00:00 +04:00
|
|
|
class proto(object):
|
2011-06-15 00:52:58 +04:00
|
|
|
def __init__(self, args):
|
|
|
|
self.args = args
|
|
|
|
def getargs(self, spec):
|
|
|
|
args = self.args
|
|
|
|
args.setdefault('*', {})
|
|
|
|
names = spec.split()
|
|
|
|
return [args[n] for n in names]
|
|
|
|
|
2012-07-13 23:47:06 +04:00
|
|
|
class clientpeer(wireproto.wirepeer):
|
2011-06-15 00:52:58 +04:00
|
|
|
def __init__(self, serverrepo):
|
|
|
|
self.serverrepo = serverrepo
|
batching: migrate basic noop batching into peer.peer
"Real" batching only makes sense for wirepeers, but it greatly
simplifies the clients of peer instances if they can be ignorant to
actual batching capabilities of that peer. By moving the
not-really-batched batching code into peer.peer, all peer instances
now work with the batching API, thus simplifying users.
This leaves a couple of name forwards in wirepeer.py. Originally I had
planned to clean those up, but it kind of unclarifies other bits of
code that want to use batching, so I think it makes sense for the
names to stay exposed by wireproto. Specifically, almost nothing is
currently aware of peer (see largefiles.proto for an example), so
making them be aware of the peer module *and* the wireproto module
seems like some abstraction leakage. I *think* the right long-term fix
would actually be to make wireproto an implementation detail that
clients wouldn't need to know about, but I don't really know what that
would entail at the moment.
As far as I'm aware, no clients of batching in third-party extensions
will need updating, which is nice icing.
2015-08-05 21:51:34 +03:00
|
|
|
|
|
|
|
def _capabilities(self):
|
|
|
|
return ['batch']
|
|
|
|
|
2011-06-15 00:52:58 +04:00
|
|
|
def _call(self, cmd, **args):
|
|
|
|
return wireproto.dispatch(self.serverrepo, proto(args), cmd)
|
|
|
|
|
2016-03-02 02:41:43 +03:00
|
|
|
def _callstream(self, cmd, **args):
|
2016-04-10 23:55:37 +03:00
|
|
|
return stringio(self._call(cmd, **args))
|
2016-03-02 02:41:43 +03:00
|
|
|
|
2011-06-15 00:52:58 +04:00
|
|
|
@wireproto.batchable
|
|
|
|
def greet(self, name):
|
|
|
|
f = wireproto.future()
|
2014-03-12 21:21:30 +04:00
|
|
|
yield {'name': mangle(name)}, f
|
2011-06-15 00:52:58 +04:00
|
|
|
yield unmangle(f.value)
|
|
|
|
|
2011-06-29 17:00:00 +04:00
|
|
|
class serverrepo(object):
|
2011-06-15 00:52:58 +04:00
|
|
|
def greet(self, name):
|
|
|
|
return "Hello, " + name
|
|
|
|
|
2013-01-06 07:41:11 +04:00
|
|
|
def filtered(self, name):
|
|
|
|
return self
|
|
|
|
|
2011-06-15 00:52:58 +04:00
|
|
|
def mangle(s):
|
|
|
|
return ''.join(chr(ord(c) + 1) for c in s)
|
|
|
|
def unmangle(s):
|
|
|
|
return ''.join(chr(ord(c) - 1) for c in s)
|
|
|
|
|
|
|
|
def greet(repo, proto, name):
|
|
|
|
return mangle(repo.greet(unmangle(name)))
|
|
|
|
|
|
|
|
wireproto.commands['greet'] = (greet, 'name',)
|
|
|
|
|
|
|
|
srv = serverrepo()
|
2012-07-13 23:47:06 +04:00
|
|
|
clt = clientpeer(srv)
|
2011-06-15 00:52:58 +04:00
|
|
|
|
2016-03-29 13:44:58 +03:00
|
|
|
print(clt.greet("Foobar"))
|
2011-06-15 00:52:58 +04:00
|
|
|
b = clt.batch()
|
wireproto: correctly escape batched args and responses (issue4739)
This issue appears to be as old as wireproto batching itself: I can
reproduce the failure as far back as 6afda0a50a20 trivially by
rebasing the test changes in this patch, which was back in the 1.9
era. I didn't test before that change, because prior to that the
testfile has a different name and I'm lazy.
Note that the test thought it was checking this case, but it actually
wasn't: it put a literal ; in the arg and response for its greet
command, but the mangle/unmangle step defined in the test meant that
instead of "Fo, =;o" going over the wire, "Gp-!><p" went instead,
which doesn't contain any special characters (those being [.=;]) and
thus not exercising the escaping. The test has been updated to use
pre-unmangled special characters, so the request is now "Fo+<:o",
which mangles to "Gp,=;p". I have confirmed that the test fails
without the adjustment to the escaping rules in wireproto.py.
No existing clients of RPC batching were depending on the old behavior
in any way. The only *actual* users of batchable RPCs in core were:
1) largefiles, wherein it batches up many statlfile calls. It sends
hexlified hashes over the wire and gets a 0, 1, or 2 back as a
response. No risk of special characters.
2) setdiscovery, which was using heads() and known(), both of which
communicate via hexlified nodes. Again, no risk of special characters.
Since the escaping functionality has been completely broken since it
was introduced, we know that it has no users. As such, we can change
the escaping mechanism without having to worry about backwards
compatibility issues.
For the curious, this was detected by chance: it happens that the
lz4-compressed text of a test file for remotefilelog compressed to
something containing a ;, which then caused the failure when I moved
remotefilelog to using batching for file content fetching.
2015-07-01 02:19:17 +03:00
|
|
|
fs = [b.greet(s) for s in ["Fo, =;:<o", "Bar"]]
|
2011-06-15 00:52:58 +04:00
|
|
|
b.submit()
|
2016-03-29 13:44:58 +03:00
|
|
|
print([f.value for f in fs])
|