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( |
|
|
342 |
|
|
|
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, '-') |
|
|
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 [] |
|
|
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' |
|
|
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