Show More
@@ -140,12 +140,10 b' def peersetup(ui, peer):' | |||||
140 | def getannotate(self, path, lastnode=None): |
|
140 | def getannotate(self, path, lastnode=None): | |
141 | if not self.capable(b'getannotate'): |
|
141 | if not self.capable(b'getannotate'): | |
142 | ui.warn(_(b'remote peer cannot provide annotate cache\n')) |
|
142 | ui.warn(_(b'remote peer cannot provide annotate cache\n')) | |
143 |
|
|
143 | return None, None | |
144 | else: |
|
144 | else: | |
145 | args = {b'path': path, b'lastnode': lastnode or b''} |
|
145 | args = {b'path': path, b'lastnode': lastnode or b''} | |
146 | f = wireprotov1peer.future() |
|
146 | return args, _parseresponse | |
147 | yield args, f |
|
|||
148 | yield _parseresponse(f.value) |
|
|||
149 |
|
147 | |||
150 | peer.__class__ = fastannotatepeer |
|
148 | peer.__class__ = fastannotatepeer | |
151 |
|
149 |
@@ -431,18 +431,19 b' def localrepolistkeys(orig, self, namesp' | |||||
431 | @wireprotov1peer.batchable |
|
431 | @wireprotov1peer.batchable | |
432 | def listkeyspatterns(self, namespace, patterns): |
|
432 | def listkeyspatterns(self, namespace, patterns): | |
433 | if not self.capable(b'pushkey'): |
|
433 | if not self.capable(b'pushkey'): | |
434 |
|
|
434 | return {}, None | |
435 | f = wireprotov1peer.future() |
|
|||
436 | self.ui.debug(b'preparing listkeys for "%s"\n' % namespace) |
|
435 | self.ui.debug(b'preparing listkeys for "%s"\n' % namespace) | |
437 | yield { |
|
436 | ||
|
437 | def decode(d): | |||
|
438 | self.ui.debug( | |||
|
439 | b'received listkey for "%s": %i bytes\n' % (namespace, len(d)) | |||
|
440 | ) | |||
|
441 | return pushkey.decodekeys(d) | |||
|
442 | ||||
|
443 | return { | |||
438 | b'namespace': encoding.fromlocal(namespace), |
|
444 | b'namespace': encoding.fromlocal(namespace), | |
439 | b'patterns': wireprototypes.encodelist(patterns), |
|
445 | b'patterns': wireprototypes.encodelist(patterns), | |
440 |
}, |
|
446 | }, decode | |
441 | d = f.value |
|
|||
442 | self.ui.debug( |
|
|||
443 | b'received listkey for "%s": %i bytes\n' % (namespace, len(d)) |
|
|||
444 | ) |
|
|||
445 | yield pushkey.decodekeys(d) |
|
|||
446 |
|
447 | |||
447 |
|
448 | |||
448 | def _readbundlerevs(bundlerepo): |
|
449 | def _readbundlerevs(bundlerepo): |
@@ -184,17 +184,18 b' def wirereposetup(ui, repo):' | |||||
184 |
|
184 | |||
185 | @wireprotov1peer.batchable |
|
185 | @wireprotov1peer.batchable | |
186 | def statlfile(self, sha): |
|
186 | def statlfile(self, sha): | |
187 | f = wireprotov1peer.future() |
|
187 | def decode(d): | |
|
188 | try: | |||
|
189 | return int(d) | |||
|
190 | except (ValueError, urlerr.httperror): | |||
|
191 | # If the server returns anything but an integer followed by a | |||
|
192 | # newline, newline, it's not speaking our language; if we get | |||
|
193 | # an HTTP error, we can't be sure the largefile is present; | |||
|
194 | # either way, consider it missing. | |||
|
195 | return 2 | |||
|
196 | ||||
188 | result = {b'sha': sha} |
|
197 | result = {b'sha': sha} | |
189 |
|
|
198 | return result, decode | |
190 | try: |
|
|||
191 | yield int(f.value) |
|
|||
192 | except (ValueError, urlerr.httperror): |
|
|||
193 | # If the server returns anything but an integer followed by a |
|
|||
194 | # newline, newline, it's not speaking our language; if we get |
|
|||
195 | # an HTTP error, we can't be sure the largefile is present; |
|
|||
196 | # either way, consider it missing. |
|
|||
197 | yield 2 |
|
|||
198 |
|
199 | |||
199 | repo.__class__ = lfileswirerepository |
|
200 | repo.__class__ = lfileswirerepository | |
200 |
|
201 |
@@ -63,12 +63,14 b' def peersetup(ui, peer):' | |||||
63 | raise error.Abort( |
|
63 | raise error.Abort( | |
64 | b'configured remotefile server does not support getfile' |
|
64 | b'configured remotefile server does not support getfile' | |
65 | ) |
|
65 | ) | |
66 | f = wireprotov1peer.future() |
|
66 | ||
67 | yield {b'file': file, b'node': node}, f |
|
67 | def decode(d): | |
68 |
code, data = |
|
68 | code, data = d.split(b'\0', 1) | |
69 | if int(code): |
|
69 | if int(code): | |
70 | raise error.LookupError(file, node, data) |
|
70 | raise error.LookupError(file, node, data) | |
71 |
|
|
71 | return data | |
|
72 | ||||
|
73 | return {b'file': file, b'node': node}, decode | |||
72 |
|
74 | |||
73 | @wireprotov1peer.batchable |
|
75 | @wireprotov1peer.batchable | |
74 | def x_rfl_getflogheads(self, path): |
|
76 | def x_rfl_getflogheads(self, path): | |
@@ -77,10 +79,11 b' def peersetup(ui, peer):' | |||||
77 | b'configured remotefile server does not ' |
|
79 | b'configured remotefile server does not ' | |
78 | b'support getflogheads' |
|
80 | b'support getflogheads' | |
79 | ) |
|
81 | ) | |
80 | f = wireprotov1peer.future() |
|
82 | ||
81 | yield {b'path': path}, f |
|
83 | def decode(d): | |
82 |
|
|
84 | return d.split(b'\n') if d else [] | |
83 | yield heads |
|
85 | ||
|
86 | return {b'path': path}, decode | |||
84 |
|
87 | |||
85 | def _updatecallstreamopts(self, command, opts): |
|
88 | def _updatecallstreamopts(self, command, opts): | |
86 | if command != b'getbundle': |
|
89 | if command != b'getbundle': |
@@ -35,7 +35,7 b' from .utils import hashutil' | |||||
35 | urlreq = util.urlreq |
|
35 | urlreq = util.urlreq | |
36 |
|
36 | |||
37 |
|
37 | |||
38 |
def batchable |
|
38 | def batchable(f): | |
39 | """annotation for batchable methods |
|
39 | """annotation for batchable methods | |
40 |
|
40 | |||
41 | Such methods must implement a coroutine as follows: |
|
41 | Such methods must implement a coroutine as follows: | |
@@ -68,33 +68,6 b' def batchable_new_style(f):' | |||||
68 | return plain |
|
68 | return plain | |
69 |
|
69 | |||
70 |
|
70 | |||
71 | def batchable(f): |
|
|||
72 | def upgraded(*args, **opts): |
|
|||
73 | batchable = f(*args, **opts) |
|
|||
74 | encoded_args_or_res, encoded_res_future = next(batchable) |
|
|||
75 | if not encoded_res_future: |
|
|||
76 | decode = None |
|
|||
77 | else: |
|
|||
78 |
|
||||
79 | def decode(d): |
|
|||
80 | encoded_res_future.set(d) |
|
|||
81 | return next(batchable) |
|
|||
82 |
|
||||
83 | return encoded_args_or_res, decode |
|
|||
84 |
|
||||
85 | setattr(upgraded, '__name__', f.__name__) |
|
|||
86 | return batchable_new_style(upgraded) |
|
|||
87 |
|
||||
88 |
|
||||
89 | class future(object): |
|
|||
90 | '''placeholder for a value to be set later''' |
|
|||
91 |
|
||||
92 | def set(self, value): |
|
|||
93 | if util.safehasattr(self, b'value'): |
|
|||
94 | raise error.RepoError(b"future is already set") |
|
|||
95 | self.value = value |
|
|||
96 |
|
||||
97 |
|
||||
98 | def encodebatchcmds(req): |
|
71 | def encodebatchcmds(req): | |
99 | """Return a ``cmds`` argument value for the ``batch`` command.""" |
|
72 | """Return a ``cmds`` argument value for the ``batch`` command.""" | |
100 | escapearg = wireprototypes.escapebatcharg |
|
73 | escapearg = wireprototypes.escapebatcharg | |
@@ -372,87 +345,90 b' class wirepeer(repository.peer):' | |||||
372 | @batchable |
|
345 | @batchable | |
373 | def lookup(self, key): |
|
346 | def lookup(self, key): | |
374 | self.requirecap(b'lookup', _(b'look up remote revision')) |
|
347 | self.requirecap(b'lookup', _(b'look up remote revision')) | |
375 | f = future() |
|
348 | ||
376 | yield {b'key': encoding.fromlocal(key)}, f |
|
349 | def decode(d): | |
377 | d = f.value |
|
350 | success, data = d[:-1].split(b" ", 1) | |
378 | success, data = d[:-1].split(b" ", 1) |
|
351 | if int(success): | |
379 | if int(success): |
|
352 | return bin(data) | |
380 |
|
|
353 | else: | |
381 | else: |
|
354 | self._abort(error.RepoError(data)) | |
382 | self._abort(error.RepoError(data)) |
|
355 | ||
|
356 | return {b'key': encoding.fromlocal(key)}, decode | |||
383 |
|
357 | |||
384 | @batchable |
|
358 | @batchable | |
385 | def heads(self): |
|
359 | def heads(self): | |
386 |
f |
|
360 | def decode(d): | |
387 | yield {}, f |
|
361 | try: | |
388 | d = f.value |
|
362 | return wireprototypes.decodelist(d[:-1]) | |
389 | try: |
|
363 | except ValueError: | |
390 | yield wireprototypes.decodelist(d[:-1]) |
|
364 | self._abort(error.ResponseError(_(b"unexpected response:"), d)) | |
391 | except ValueError: |
|
365 | ||
392 | self._abort(error.ResponseError(_(b"unexpected response:"), d)) |
|
366 | return {}, decode | |
393 |
|
367 | |||
394 | @batchable |
|
368 | @batchable | |
395 | def known(self, nodes): |
|
369 | def known(self, nodes): | |
396 |
f |
|
370 | def decode(d): | |
397 | yield {b'nodes': wireprototypes.encodelist(nodes)}, f |
|
371 | try: | |
398 | d = f.value |
|
372 | return [bool(int(b)) for b in pycompat.iterbytestr(d)] | |
399 | try: |
|
373 | except ValueError: | |
400 | yield [bool(int(b)) for b in pycompat.iterbytestr(d)] |
|
374 | self._abort(error.ResponseError(_(b"unexpected response:"), d)) | |
401 | except ValueError: |
|
375 | ||
402 | self._abort(error.ResponseError(_(b"unexpected response:"), d)) |
|
376 | return {b'nodes': wireprototypes.encodelist(nodes)}, decode | |
403 |
|
377 | |||
404 | @batchable |
|
378 | @batchable | |
405 | def branchmap(self): |
|
379 | def branchmap(self): | |
406 |
f |
|
380 | def decode(d): | |
407 | yield {}, f |
|
381 | try: | |
408 | d = f.value |
|
382 | branchmap = {} | |
409 | try: |
|
383 | for branchpart in d.splitlines(): | |
410 | branchmap = {} |
|
384 | branchname, branchheads = branchpart.split(b' ', 1) | |
411 | for branchpart in d.splitlines(): |
|
385 | branchname = encoding.tolocal(urlreq.unquote(branchname)) | |
412 | branchname, branchheads = branchpart.split(b' ', 1) |
|
386 | branchheads = wireprototypes.decodelist(branchheads) | |
413 | branchname = encoding.tolocal(urlreq.unquote(branchname)) |
|
387 | branchmap[branchname] = branchheads | |
414 | branchheads = wireprototypes.decodelist(branchheads) |
|
388 | return branchmap | |
415 | branchmap[branchname] = branchheads |
|
389 | except TypeError: | |
416 | yield branchmap |
|
390 | self._abort(error.ResponseError(_(b"unexpected response:"), d)) | |
417 | except TypeError: |
|
391 | ||
418 | self._abort(error.ResponseError(_(b"unexpected response:"), d)) |
|
392 | return {}, decode | |
419 |
|
393 | |||
420 | @batchable |
|
394 | @batchable | |
421 | def listkeys(self, namespace): |
|
395 | def listkeys(self, namespace): | |
422 | if not self.capable(b'pushkey'): |
|
396 | if not self.capable(b'pushkey'): | |
423 |
|
|
397 | return {}, None | |
424 | f = future() |
|
|||
425 | self.ui.debug(b'preparing listkeys for "%s"\n' % namespace) |
|
398 | self.ui.debug(b'preparing listkeys for "%s"\n' % namespace) | |
426 | yield {b'namespace': encoding.fromlocal(namespace)}, f |
|
399 | ||
427 | d = f.value |
|
400 | def decode(d): | |
428 | self.ui.debug( |
|
401 | self.ui.debug( | |
429 | b'received listkey for "%s": %i bytes\n' % (namespace, len(d)) |
|
402 | b'received listkey for "%s": %i bytes\n' % (namespace, len(d)) | |
430 | ) |
|
403 | ) | |
431 |
|
|
404 | return pushkeymod.decodekeys(d) | |
|
405 | ||||
|
406 | return {b'namespace': encoding.fromlocal(namespace)}, decode | |||
432 |
|
407 | |||
433 | @batchable |
|
408 | @batchable | |
434 | def pushkey(self, namespace, key, old, new): |
|
409 | def pushkey(self, namespace, key, old, new): | |
435 | if not self.capable(b'pushkey'): |
|
410 | if not self.capable(b'pushkey'): | |
436 |
|
|
411 | return False, None | |
437 | f = future() |
|
|||
438 | self.ui.debug(b'preparing pushkey for "%s:%s"\n' % (namespace, key)) |
|
412 | self.ui.debug(b'preparing pushkey for "%s:%s"\n' % (namespace, key)) | |
439 | yield { |
|
413 | ||
|
414 | def decode(d): | |||
|
415 | d, output = d.split(b'\n', 1) | |||
|
416 | try: | |||
|
417 | d = bool(int(d)) | |||
|
418 | except ValueError: | |||
|
419 | raise error.ResponseError( | |||
|
420 | _(b'push failed (unexpected response):'), d | |||
|
421 | ) | |||
|
422 | for l in output.splitlines(True): | |||
|
423 | self.ui.status(_(b'remote: '), l) | |||
|
424 | return d | |||
|
425 | ||||
|
426 | return { | |||
440 | b'namespace': encoding.fromlocal(namespace), |
|
427 | b'namespace': encoding.fromlocal(namespace), | |
441 | b'key': encoding.fromlocal(key), |
|
428 | b'key': encoding.fromlocal(key), | |
442 | b'old': encoding.fromlocal(old), |
|
429 | b'old': encoding.fromlocal(old), | |
443 | b'new': encoding.fromlocal(new), |
|
430 | b'new': encoding.fromlocal(new), | |
444 |
}, |
|
431 | }, decode | |
445 | d = f.value |
|
|||
446 | d, output = d.split(b'\n', 1) |
|
|||
447 | try: |
|
|||
448 | d = bool(int(d)) |
|
|||
449 | except ValueError: |
|
|||
450 | raise error.ResponseError( |
|
|||
451 | _(b'push failed (unexpected response):'), d |
|
|||
452 | ) |
|
|||
453 | for l in output.splitlines(True): |
|
|||
454 | self.ui.status(_(b'remote: '), l) |
|
|||
455 | yield d |
|
|||
456 |
|
432 | |||
457 | def stream_out(self): |
|
433 | def stream_out(self): | |
458 | return self._callstream(b'stream_out') |
|
434 | return self._callstream(b'stream_out') |
@@ -214,14 +214,11 b' class remotething(thing):' | |||||
214 | mangle(two), |
|
214 | mangle(two), | |
215 | ), |
|
215 | ), | |
216 | ] |
|
216 | ] | |
217 | encoded_res_future = wireprotov1peer.future() |
|
217 | return encoded_args, unmangle | |
218 | yield encoded_args, encoded_res_future |
|
|||
219 | yield unmangle(encoded_res_future.value) |
|
|||
220 |
|
218 | |||
221 | @wireprotov1peer.batchable |
|
219 | @wireprotov1peer.batchable | |
222 | def bar(self, b, a): |
|
220 | def bar(self, b, a): | |
223 | encresref = wireprotov1peer.future() |
|
221 | return [ | |
224 | yield [ |
|
|||
225 | ( |
|
222 | ( | |
226 | b'b', |
|
223 | b'b', | |
227 | mangle(b), |
|
224 | mangle(b), | |
@@ -230,8 +227,7 b' class remotething(thing):' | |||||
230 | b'a', |
|
227 | b'a', | |
231 | mangle(a), |
|
228 | mangle(a), | |
232 | ), |
|
229 | ), | |
233 |
], |
|
230 | ], unmangle | |
234 | yield unmangle(encresref.value) |
|
|||
235 |
|
231 | |||
236 | # greet is coded directly. It therefore does not support batching. If it |
|
232 | # greet is coded directly. It therefore does not support batching. If it | |
237 | # does appear in a batch, the batch is split around greet, and the call to |
|
233 | # does appear in a batch, the batch is split around greet, and the call to |
@@ -75,9 +75,7 b' class clientpeer(wireprotov1peer.wirepee' | |||||
75 |
|
75 | |||
76 | @wireprotov1peer.batchable |
|
76 | @wireprotov1peer.batchable | |
77 | def greet(self, name): |
|
77 | def greet(self, name): | |
78 | f = wireprotov1peer.future() |
|
78 | return {b'name': mangle(name)}, unmangle | |
79 | yield {b'name': mangle(name)}, f |
|
|||
80 | yield unmangle(f.value) |
|
|||
81 |
|
79 | |||
82 |
|
80 | |||
83 | class serverrepo(object): |
|
81 | class serverrepo(object): |
General Comments 0
You need to be logged in to leave comments.
Login now