124 return [] |
124 return [] |
125 |
125 |
126 def encodelist(l, sep=' '): |
126 def encodelist(l, sep=' '): |
127 return sep.join(map(hex, l)) |
127 return sep.join(map(hex, l)) |
128 |
128 |
|
129 # batched call argument encoding |
|
130 |
|
131 def escapearg(plain): |
|
132 return (plain |
|
133 .replace(':', '::') |
|
134 .replace(',', ':,') |
|
135 .replace(';', ':;') |
|
136 .replace('=', ':=')) |
|
137 |
|
138 def unescapearg(escaped): |
|
139 return (escaped |
|
140 .replace(':=', '=') |
|
141 .replace(':;', ';') |
|
142 .replace(':,', ',') |
|
143 .replace('::', ':')) |
|
144 |
129 # client side |
145 # client side |
130 |
146 |
|
147 def todict(**args): |
|
148 return args |
|
149 |
131 class wirerepository(repo.repository): |
150 class wirerepository(repo.repository): |
|
151 |
|
152 def batch(self): |
|
153 return remotebatch(self) |
|
154 def _submitbatch(self, req): |
|
155 cmds = [] |
|
156 for op, argsdict in req: |
|
157 args = ','.join('%s=%s' % p for p in argsdict.iteritems()) |
|
158 cmds.append('%s %s' % (op, args)) |
|
159 rsp = self._call("batch", cmds=';'.join(cmds)) |
|
160 return rsp.split(';') |
|
161 def _submitone(self, op, args): |
|
162 return self._call(op, **args) |
|
163 |
132 def lookup(self, key): |
164 def lookup(self, key): |
133 self.requirecap('lookup', _('look up remote revision')) |
165 self.requirecap('lookup', _('look up remote revision')) |
134 d = self._call("lookup", key=encoding.fromlocal(key)) |
166 d = self._call("lookup", key=encoding.fromlocal(key)) |
135 success, data = d[:-1].split(" ", 1) |
167 success, data = d[:-1].split(" ", 1) |
136 if int(success): |
168 if int(success): |
300 if others: |
332 if others: |
301 sys.stderr.write("abort: %s got unexpected arguments %s\n" |
333 sys.stderr.write("abort: %s got unexpected arguments %s\n" |
302 % (cmd, ",".join(others))) |
334 % (cmd, ",".join(others))) |
303 return opts |
335 return opts |
304 |
336 |
|
337 def batch(repo, proto, cmds, others): |
|
338 res = [] |
|
339 for pair in cmds.split(';'): |
|
340 op, args = pair.split(' ', 1) |
|
341 vals = {} |
|
342 for a in args.split(','): |
|
343 if a: |
|
344 n, v = a.split('=') |
|
345 vals[n] = unescapearg(v) |
|
346 func, spec = commands[op] |
|
347 if spec: |
|
348 keys = spec.split() |
|
349 data = {} |
|
350 for k in keys: |
|
351 if k == '*': |
|
352 star = {} |
|
353 for key in vals.keys(): |
|
354 if key not in keys: |
|
355 star[key] = vals[key] |
|
356 data['*'] = star |
|
357 else: |
|
358 data[k] = vals[k] |
|
359 result = func(repo, proto, *[data[k] for k in keys]) |
|
360 else: |
|
361 result = func(repo, proto) |
|
362 res.append(escapearg(result)) |
|
363 return ';'.join(res) |
|
364 |
305 def between(repo, proto, pairs): |
365 def between(repo, proto, pairs): |
306 pairs = [decodelist(p, '-') for p in pairs.split(" ")] |
366 pairs = [decodelist(p, '-') for p in pairs.split(" ")] |
307 r = [] |
367 r = [] |
308 for b in repo.between(pairs): |
368 for b in repo.between(pairs): |
309 r.append(encodelist(b) + "\n") |
369 r.append(encodelist(b) + "\n") |
325 r.append(encodelist(b) + "\n") |
385 r.append(encodelist(b) + "\n") |
326 return "".join(r) |
386 return "".join(r) |
327 |
387 |
328 def capabilities(repo, proto): |
388 def capabilities(repo, proto): |
329 caps = ('lookup changegroupsubset branchmap pushkey known getbundle ' |
389 caps = ('lookup changegroupsubset branchmap pushkey known getbundle ' |
330 'unbundlehash').split() |
390 'unbundlehash batch').split() |
331 if _allowstream(repo.ui): |
391 if _allowstream(repo.ui): |
332 requiredformats = repo.requirements & repo.supportedformats |
392 requiredformats = repo.requirements & repo.supportedformats |
333 # if our local revlogs are just revlogv1, add 'stream' cap |
393 # if our local revlogs are just revlogv1, add 'stream' cap |
334 if not requiredformats - set(('revlogv1',)): |
394 if not requiredformats - set(('revlogv1',)): |
335 caps.append('stream') |
395 caps.append('stream') |
504 finally: |
564 finally: |
505 fp.close() |
565 fp.close() |
506 os.unlink(tempname) |
566 os.unlink(tempname) |
507 |
567 |
508 commands = { |
568 commands = { |
|
569 'batch': (batch, 'cmds *'), |
509 'between': (between, 'pairs'), |
570 'between': (between, 'pairs'), |
510 'branchmap': (branchmap, ''), |
571 'branchmap': (branchmap, ''), |
511 'branches': (branches, 'nodes'), |
572 'branches': (branches, 'nodes'), |
512 'capabilities': (capabilities, ''), |
573 'capabilities': (capabilities, ''), |
513 'changegroup': (changegroup, 'roots'), |
574 'changegroup': (changegroup, 'roots'), |