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