Show More
@@ -127,6 +127,7 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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( |
|
315 | heads = wireprototypes.encodelist( | |
342 |
|
|
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 b' 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 b' 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, '-') |
|
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 [] |
|
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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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 b' 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' |
|
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 b' 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 b'' | |||||
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 b' 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