##// END OF EJS Templates
wireproto: move value encoding functions to wireprototypes (API)...
Gregory Szorc -
r37630:5e71dea7 default
parent child Browse files
Show More
@@ -127,6 +127,7 from mercurial import (
127 registrar,
127 registrar,
128 util,
128 util,
129 wireproto,
129 wireproto,
130 wireprototypes,
130 )
131 )
131
132
132 from . import (
133 from . import (
@@ -331,7 +332,7 def _checkheads(orig, pushop):
331 return orig(pushop)
332 return orig(pushop)
332
333
333 def wireprotolistkeyspatterns(repo, proto, namespace, patterns):
334 def wireprotolistkeyspatterns(repo, proto, namespace, patterns):
334 patterns = wireproto.decodelist(patterns)
335 patterns = wireprototypes.decodelist(patterns)
335 d = repo.listkeys(encoding.tolocal(namespace), patterns).iteritems()
336 d = repo.listkeys(encoding.tolocal(namespace), patterns).iteritems()
336 return pushkey.encodekeys(d)
337 return pushkey.encodekeys(d)
337
338
@@ -361,7 +362,7 def listkeyspatterns(self, namespace, pa
361 (namespace, patterns))
362 (namespace, patterns))
362 yield {
363 yield {
363 'namespace': encoding.fromlocal(namespace),
364 'namespace': encoding.fromlocal(namespace),
364 'patterns': wireproto.encodelist(patterns)
365 'patterns': wireprototypes.encodelist(patterns)
365 }, f
366 }, f
366 d = f.value
367 d = f.value
367 self.ui.debug('received listkey for "%s": %i bytes\n'
368 self.ui.debug('received listkey for "%s": %i bytes\n'
@@ -115,37 +115,11 class remoteiterbatcher(peer.iterbatcher
115 batchable = peer.batchable
115 batchable = peer.batchable
116 future = peer.future
116 future = peer.future
117
117
118 # list of nodes encoding / decoding
119
120 def decodelist(l, sep=' '):
121 if l:
122 return [bin(v) for v in l.split(sep)]
123 return []
124
125 def encodelist(l, sep=' '):
126 try:
127 return sep.join(map(hex, l))
128 except TypeError:
129 raise
130
131 # batched call argument encoding
132
133 def escapearg(plain):
134 return (plain
135 .replace(':', ':c')
136 .replace(',', ':o')
137 .replace(';', ':s')
138 .replace('=', ':e'))
139
140 def unescapearg(escaped):
141 return (escaped
142 .replace(':e', '=')
143 .replace(':s', ';')
144 .replace(':o', ',')
145 .replace(':c', ':'))
146
118
147 def encodebatchcmds(req):
119 def encodebatchcmds(req):
148 """Return a ``cmds`` argument value for the ``batch`` command."""
120 """Return a ``cmds`` argument value for the ``batch`` command."""
121 escapearg = wireprototypes.escapebatcharg
122
149 cmds = []
123 cmds = []
150 for op, argsdict in req:
124 for op, argsdict in req:
151 # Old servers didn't properly unescape argument names. So prevent
125 # Old servers didn't properly unescape argument names. So prevent
@@ -227,14 +201,14 class wirepeer(repository.legacypeer):
227 yield {}, f
201 yield {}, f
228 d = f.value
202 d = f.value
229 try:
203 try:
230 yield decodelist(d[:-1])
204 yield wireprototypes.decodelist(d[:-1])
231 except ValueError:
205 except ValueError:
232 self._abort(error.ResponseError(_("unexpected response:"), d))
206 self._abort(error.ResponseError(_("unexpected response:"), d))
233
207
234 @batchable
208 @batchable
235 def known(self, nodes):
209 def known(self, nodes):
236 f = future()
210 f = future()
237 yield {'nodes': encodelist(nodes)}, f
211 yield {'nodes': wireprototypes.encodelist(nodes)}, f
238 d = f.value
212 d = f.value
239 try:
213 try:
240 yield [bool(int(b)) for b in d]
214 yield [bool(int(b)) for b in d]
@@ -251,7 +225,7 class wirepeer(repository.legacypeer):
251 for branchpart in d.splitlines():
225 for branchpart in d.splitlines():
252 branchname, branchheads = branchpart.split(' ', 1)
226 branchname, branchheads = branchpart.split(' ', 1)
253 branchname = encoding.tolocal(urlreq.unquote(branchname))
227 branchname = encoding.tolocal(urlreq.unquote(branchname))
254 branchheads = decodelist(branchheads)
228 branchheads = wireprototypes.decodelist(branchheads)
255 branchmap[branchname] = branchheads
229 branchmap[branchname] = branchheads
256 yield branchmap
230 yield branchmap
257 except TypeError:
231 except TypeError:
@@ -306,7 +280,7 class wirepeer(repository.legacypeer):
306 raise error.ProgrammingError(
280 raise error.ProgrammingError(
307 'Unexpectedly None keytype for key %s' % key)
281 'Unexpectedly None keytype for key %s' % key)
308 elif keytype == 'nodes':
282 elif keytype == 'nodes':
309 value = encodelist(value)
283 value = wireprototypes.encodelist(value)
310 elif keytype == 'csv':
284 elif keytype == 'csv':
311 value = ','.join(value)
285 value = ','.join(value)
312 elif keytype == 'scsv':
286 elif keytype == 'scsv':
@@ -338,10 +312,10 class wirepeer(repository.legacypeer):
338 '''
312 '''
339
313
340 if heads != ['force'] and self.capable('unbundlehash'):
314 if heads != ['force'] and self.capable('unbundlehash'):
341 heads = encodelist(['hashed',
315 heads = wireprototypes.encodelist(
342 hashlib.sha1(''.join(sorted(heads))).digest()])
316 ['hashed', hashlib.sha1(''.join(sorted(heads))).digest()])
343 else:
317 else:
344 heads = encodelist(heads)
318 heads = wireprototypes.encodelist(heads)
345
319
346 if util.safehasattr(cg, 'deltaheader'):
320 if util.safehasattr(cg, 'deltaheader'):
347 # this a bundle10, do the old style call sequence
321 # this a bundle10, do the old style call sequence
@@ -368,10 +342,10 class wirepeer(repository.legacypeer):
368 # Begin of ipeerlegacycommands interface.
342 # Begin of ipeerlegacycommands interface.
369
343
370 def branches(self, nodes):
344 def branches(self, nodes):
371 n = encodelist(nodes)
345 n = wireprototypes.encodelist(nodes)
372 d = self._call("branches", nodes=n)
346 d = self._call("branches", nodes=n)
373 try:
347 try:
374 br = [tuple(decodelist(b)) for b in d.splitlines()]
348 br = [tuple(wireprototypes.decodelist(b)) for b in d.splitlines()]
375 return br
349 return br
376 except ValueError:
350 except ValueError:
377 self._abort(error.ResponseError(_("unexpected response:"), d))
351 self._abort(error.ResponseError(_("unexpected response:"), d))
@@ -380,23 +354,25 class wirepeer(repository.legacypeer):
380 batch = 8 # avoid giant requests
354 batch = 8 # avoid giant requests
381 r = []
355 r = []
382 for i in xrange(0, len(pairs), batch):
356 for i in xrange(0, len(pairs), batch):
383 n = " ".join([encodelist(p, '-') for p in pairs[i:i + batch]])
357 n = " ".join([wireprototypes.encodelist(p, '-')
358 for p in pairs[i:i + batch]])
384 d = self._call("between", pairs=n)
359 d = self._call("between", pairs=n)
385 try:
360 try:
386 r.extend(l and decodelist(l) or [] for l in d.splitlines())
361 r.extend(l and wireprototypes.decodelist(l) or []
362 for l in d.splitlines())
387 except ValueError:
363 except ValueError:
388 self._abort(error.ResponseError(_("unexpected response:"), d))
364 self._abort(error.ResponseError(_("unexpected response:"), d))
389 return r
365 return r
390
366
391 def changegroup(self, nodes, kind):
367 def changegroup(self, nodes, kind):
392 n = encodelist(nodes)
368 n = wireprototypes.encodelist(nodes)
393 f = self._callcompressable("changegroup", roots=n)
369 f = self._callcompressable("changegroup", roots=n)
394 return changegroupmod.cg1unpacker(f, 'UN')
370 return changegroupmod.cg1unpacker(f, 'UN')
395
371
396 def changegroupsubset(self, bases, heads, kind):
372 def changegroupsubset(self, bases, heads, kind):
397 self.requirecap('changegroupsubset', _('look up remote changes'))
373 self.requirecap('changegroupsubset', _('look up remote changes'))
398 bases = encodelist(bases)
374 bases = wireprototypes.encodelist(bases)
399 heads = encodelist(heads)
375 heads = wireprototypes.encodelist(heads)
400 f = self._callcompressable("changegroupsubset",
376 f = self._callcompressable("changegroupsubset",
401 bases=bases, heads=heads)
377 bases=bases, heads=heads)
402 return changegroupmod.cg1unpacker(f, 'UN')
378 return changegroupmod.cg1unpacker(f, 'UN')
@@ -415,6 +391,8 class wirepeer(repository.legacypeer):
415 msg = 'devel-peer-request: - %s (%d arguments)\n'
391 msg = 'devel-peer-request: - %s (%d arguments)\n'
416 ui.debug(msg % (op, len(args)))
392 ui.debug(msg % (op, len(args)))
417
393
394 unescapearg = wireprototypes.unescapebatcharg
395
418 rsp = self._callstream("batch", cmds=encodebatchcmds(req))
396 rsp = self._callstream("batch", cmds=encodebatchcmds(req))
419 chunk = rsp.read(1024)
397 chunk = rsp.read(1024)
420 work = [chunk]
398 work = [chunk]
@@ -793,6 +771,7 def wireprotocommand(name, args=None, tr
793 @wireprotocommand('batch', 'cmds *', permission='pull',
771 @wireprotocommand('batch', 'cmds *', permission='pull',
794 transportpolicy=POLICY_V1_ONLY)
772 transportpolicy=POLICY_V1_ONLY)
795 def batch(repo, proto, cmds, others):
773 def batch(repo, proto, cmds, others):
774 unescapearg = wireprototypes.unescapebatcharg
796 repo = repo.filtered("served")
775 repo = repo.filtered("served")
797 res = []
776 res = []
798 for pair in cmds.split(';'):
777 for pair in cmds.split(';'):
@@ -832,17 +811,17 def batch(repo, proto, cmds, others):
832 assert isinstance(result, (wireprototypes.bytesresponse, bytes))
811 assert isinstance(result, (wireprototypes.bytesresponse, bytes))
833 if isinstance(result, wireprototypes.bytesresponse):
812 if isinstance(result, wireprototypes.bytesresponse):
834 result = result.data
813 result = result.data
835 res.append(escapearg(result))
814 res.append(wireprototypes.escapebatcharg(result))
836
815
837 return wireprototypes.bytesresponse(';'.join(res))
816 return wireprototypes.bytesresponse(';'.join(res))
838
817
839 @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY,
818 @wireprotocommand('between', 'pairs', transportpolicy=POLICY_V1_ONLY,
840 permission='pull')
819 permission='pull')
841 def between(repo, proto, pairs):
820 def between(repo, proto, pairs):
842 pairs = [decodelist(p, '-') for p in pairs.split(" ")]
821 pairs = [wireprototypes.decodelist(p, '-') for p in pairs.split(" ")]
843 r = []
822 r = []
844 for b in repo.between(pairs):
823 for b in repo.between(pairs):
845 r.append(encodelist(b) + "\n")
824 r.append(wireprototypes.encodelist(b) + "\n")
846
825
847 return wireprototypes.bytesresponse(''.join(r))
826 return wireprototypes.bytesresponse(''.join(r))
848
827
@@ -853,7 +832,7 def branchmap(repo, proto):
853 heads = []
832 heads = []
854 for branch, nodes in branchmap.iteritems():
833 for branch, nodes in branchmap.iteritems():
855 branchname = urlreq.quote(encoding.fromlocal(branch))
834 branchname = urlreq.quote(encoding.fromlocal(branch))
856 branchnodes = encodelist(nodes)
835 branchnodes = wireprototypes.encodelist(nodes)
857 heads.append('%s %s' % (branchname, branchnodes))
836 heads.append('%s %s' % (branchname, branchnodes))
858
837
859 return wireprototypes.bytesresponse('\n'.join(heads))
838 return wireprototypes.bytesresponse('\n'.join(heads))
@@ -861,10 +840,10 def branchmap(repo, proto):
861 @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY,
840 @wireprotocommand('branches', 'nodes', transportpolicy=POLICY_V1_ONLY,
862 permission='pull')
841 permission='pull')
863 def branches(repo, proto, nodes):
842 def branches(repo, proto, nodes):
864 nodes = decodelist(nodes)
843 nodes = wireprototypes.decodelist(nodes)
865 r = []
844 r = []
866 for b in repo.branches(nodes):
845 for b in repo.branches(nodes):
867 r.append(encodelist(b) + "\n")
846 r.append(wireprototypes.encodelist(b) + "\n")
868
847
869 return wireprototypes.bytesresponse(''.join(r))
848 return wireprototypes.bytesresponse(''.join(r))
870
849
@@ -931,7 +910,7 def capabilities(repo, proto):
931 @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY,
910 @wireprotocommand('changegroup', 'roots', transportpolicy=POLICY_V1_ONLY,
932 permission='pull')
911 permission='pull')
933 def changegroup(repo, proto, roots):
912 def changegroup(repo, proto, roots):
934 nodes = decodelist(roots)
913 nodes = wireprototypes.decodelist(roots)
935 outgoing = discovery.outgoing(repo, missingroots=nodes,
914 outgoing = discovery.outgoing(repo, missingroots=nodes,
936 missingheads=repo.heads())
915 missingheads=repo.heads())
937 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
916 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
@@ -942,8 +921,8 def changegroup(repo, proto, roots):
942 transportpolicy=POLICY_V1_ONLY,
921 transportpolicy=POLICY_V1_ONLY,
943 permission='pull')
922 permission='pull')
944 def changegroupsubset(repo, proto, bases, heads):
923 def changegroupsubset(repo, proto, bases, heads):
945 bases = decodelist(bases)
924 bases = wireprototypes.decodelist(bases)
946 heads = decodelist(heads)
925 heads = wireprototypes.decodelist(heads)
947 outgoing = discovery.outgoing(repo, missingroots=bases,
926 outgoing = discovery.outgoing(repo, missingroots=bases,
948 missingheads=heads)
927 missingheads=heads)
949 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
928 cg = changegroupmod.makechangegroup(repo, outgoing, '01', 'serve')
@@ -1029,7 +1008,7 def getbundle(repo, proto, others):
1029 for k, v in opts.iteritems():
1008 for k, v in opts.iteritems():
1030 keytype = gboptsmap[k]
1009 keytype = gboptsmap[k]
1031 if keytype == 'nodes':
1010 if keytype == 'nodes':
1032 opts[k] = decodelist(v)
1011 opts[k] = wireprototypes.decodelist(v)
1033 elif keytype == 'csv':
1012 elif keytype == 'csv':
1034 opts[k] = list(v.split(','))
1013 opts[k] = list(v.split(','))
1035 elif keytype == 'scsv':
1014 elif keytype == 'scsv':
@@ -1101,7 +1080,7 def getbundle(repo, proto, others):
1101 @wireprotocommand('heads', permission='pull', transportpolicy=POLICY_V1_ONLY)
1080 @wireprotocommand('heads', permission='pull', transportpolicy=POLICY_V1_ONLY)
1102 def heads(repo, proto):
1081 def heads(repo, proto):
1103 h = repo.heads()
1082 h = repo.heads()
1104 return wireprototypes.bytesresponse(encodelist(h) + '\n')
1083 return wireprototypes.bytesresponse(wireprototypes.encodelist(h) + '\n')
1105
1084
1106 @wireprotocommand('hello', permission='pull', transportpolicy=POLICY_V1_ONLY)
1085 @wireprotocommand('hello', permission='pull', transportpolicy=POLICY_V1_ONLY)
1107 def hello(repo, proto):
1086 def hello(repo, proto):
@@ -1140,7 +1119,8 def lookup(repo, proto, key):
1140 @wireprotocommand('known', 'nodes *', permission='pull',
1119 @wireprotocommand('known', 'nodes *', permission='pull',
1141 transportpolicy=POLICY_V1_ONLY)
1120 transportpolicy=POLICY_V1_ONLY)
1142 def known(repo, proto, nodes, others):
1121 def known(repo, proto, nodes, others):
1143 v = ''.join(b and '1' or '0' for b in repo.known(decodelist(nodes)))
1122 v = ''.join(b and '1' or '0'
1123 for b in repo.known(wireprototypes.decodelist(nodes)))
1144 return wireprototypes.bytesresponse(v)
1124 return wireprototypes.bytesresponse(v)
1145
1125
1146 @wireprotocommand('protocaps', 'caps', permission='pull',
1126 @wireprotocommand('protocaps', 'caps', permission='pull',
@@ -1185,7 +1165,7 def stream(repo, proto):
1185 @wireprotocommand('unbundle', 'heads', permission='push',
1165 @wireprotocommand('unbundle', 'heads', permission='push',
1186 transportpolicy=POLICY_V1_ONLY)
1166 transportpolicy=POLICY_V1_ONLY)
1187 def unbundle(repo, proto, heads):
1167 def unbundle(repo, proto, heads):
1188 their_heads = decodelist(heads)
1168 their_heads = wireprototypes.decodelist(heads)
1189
1169
1190 with proto.mayberedirectstdio() as output:
1170 with proto.mayberedirectstdio() as output:
1191 try:
1171 try:
@@ -5,6 +5,10
5
5
6 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 from .node import (
9 bin,
10 hex,
11 )
8 from .thirdparty.zope import (
12 from .thirdparty.zope import (
9 interface as zi,
13 interface as zi,
10 )
14 )
@@ -102,6 +106,34 class cborresponse(object):
102 def __init__(self, v):
106 def __init__(self, v):
103 self.value = v
107 self.value = v
104
108
109 # list of nodes encoding / decoding
110 def decodelist(l, sep=' '):
111 if l:
112 return [bin(v) for v in l.split(sep)]
113 return []
114
115 def encodelist(l, sep=' '):
116 try:
117 return sep.join(map(hex, l))
118 except TypeError:
119 raise
120
121 # batched call argument encoding
122
123 def escapebatcharg(plain):
124 return (plain
125 .replace(':', ':c')
126 .replace(',', ':o')
127 .replace(';', ':s')
128 .replace('=', ':e'))
129
130 def unescapebatcharg(escaped):
131 return (escaped
132 .replace(':e', '=')
133 .replace(':s', ';')
134 .replace(':o', ',')
135 .replace(':c', ':'))
136
105 class baseprotocolhandler(zi.Interface):
137 class baseprotocolhandler(zi.Interface):
106 """Abstract base class for wire protocol handlers.
138 """Abstract base class for wire protocol handlers.
107
139
General Comments 0
You need to be logged in to leave comments. Login now