##// END OF EJS Templates
mercurial: Explicitly disable largefiles extension when no config value is present for it....
Martin Bornhold -
r36:368b34ff default
parent child Browse files
Show More
@@ -1,692 +1,700 b''
1 1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 2 # Copyright (C) 2014-2016 RodeCode GmbH
3 3 #
4 4 # This program is free software; you can redistribute it and/or modify
5 5 # it under the terms of the GNU General Public License as published by
6 6 # the Free Software Foundation; either version 3 of the License, or
7 7 # (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software Foundation,
16 16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 17
18 18 import io
19 19 import logging
20 20 import stat
21 21 import sys
22 22 import urllib
23 23 import urllib2
24 24
25 25 from hgext import largefiles, rebase
26 26 from hgext.strip import strip as hgext_strip
27 27 from mercurial import commands
28 28 from mercurial import unionrepo
29 29
30 30 from vcsserver import exceptions
31 31 from vcsserver.base import RepoFactory
32 32 from vcsserver.hgcompat import (
33 33 archival, bin, clone, config as hgconfig, diffopts, hex, hg_url,
34 34 httpbasicauthhandler, httpdigestauthhandler, httppeer, localrepository,
35 35 match, memctx, exchange, memfilectx, nullrev, patch, peer, revrange, ui,
36 36 Abort, LookupError, RepoError, RepoLookupError, InterventionRequired,
37 37 RequirementError)
38 38
39 39 log = logging.getLogger(__name__)
40 40
41 41
42 42 def make_ui_from_config(repo_config):
43 43 baseui = ui.ui()
44 44
45 45 # clean the baseui object
46 46 baseui._ocfg = hgconfig.config()
47 47 baseui._ucfg = hgconfig.config()
48 48 baseui._tcfg = hgconfig.config()
49 49
50 50 for section, option, value in repo_config:
51 51 baseui.setconfig(section, option, value)
52 52
53 53 # make our hgweb quiet so it doesn't print output
54 54 baseui.setconfig('ui', 'quiet', 'true')
55 55
56 56 # force mercurial to only use 1 thread, otherwise it may try to set a
57 57 # signal in a non-main thread, thus generating a ValueError.
58 58 baseui.setconfig('worker', 'numcpus', 1)
59 59
60 # If there is no config for the largefiles extension, we explicitly disable
61 # it here. This overrides settings from repositories hgrc file. Recent
62 # mercurial versions enable largefiles in hgrc on clone from largefile
63 # repo.
64 if not baseui.hasconfig('extensions', 'largefiles'):
65 log.debug('Explicitly disable largefiles extension for repo.')
66 baseui.setconfig('extensions', 'largefiles', '!')
67
60 68 return baseui
61 69
62 70
63 71 def reraise_safe_exceptions(func):
64 72 """Decorator for converting mercurial exceptions to something neutral."""
65 73 def wrapper(*args, **kwargs):
66 74 try:
67 75 return func(*args, **kwargs)
68 76 except (Abort, InterventionRequired):
69 77 raise_from_original(exceptions.AbortException)
70 78 except RepoLookupError:
71 79 raise_from_original(exceptions.LookupException)
72 80 except RequirementError:
73 81 raise_from_original(exceptions.RequirementException)
74 82 except RepoError:
75 83 raise_from_original(exceptions.VcsException)
76 84 except LookupError:
77 85 raise_from_original(exceptions.LookupException)
78 86 except Exception as e:
79 87 if not hasattr(e, '_vcs_kind'):
80 88 log.exception("Unhandled exception in hg remote call")
81 89 raise_from_original(exceptions.UnhandledException)
82 90 raise
83 91 return wrapper
84 92
85 93
86 94 def raise_from_original(new_type):
87 95 """
88 96 Raise a new exception type with original args and traceback.
89 97 """
90 98 _, original, traceback = sys.exc_info()
91 99 try:
92 100 raise new_type(*original.args), None, traceback
93 101 finally:
94 102 del traceback
95 103
96 104
97 105 class MercurialFactory(RepoFactory):
98 106
99 107 def _create_config(self, config, hooks=True):
100 108 if not hooks:
101 109 hooks_to_clean = frozenset((
102 110 'changegroup.repo_size', 'preoutgoing.pre_pull',
103 111 'outgoing.pull_logger', 'prechangegroup.pre_push'))
104 112 new_config = []
105 113 for section, option, value in config:
106 114 if section == 'hooks' and option in hooks_to_clean:
107 115 continue
108 116 new_config.append((section, option, value))
109 117 config = new_config
110 118
111 119 baseui = make_ui_from_config(config)
112 120 return baseui
113 121
114 122 def _create_repo(self, wire, create):
115 123 baseui = self._create_config(wire["config"])
116 124 return localrepository(baseui, wire["path"], create)
117 125
118 126
119 127 class HgRemote(object):
120 128
121 129 def __init__(self, factory):
122 130 self._factory = factory
123 131
124 132 self._bulk_methods = {
125 133 "affected_files": self.ctx_files,
126 134 "author": self.ctx_user,
127 135 "branch": self.ctx_branch,
128 136 "children": self.ctx_children,
129 137 "date": self.ctx_date,
130 138 "message": self.ctx_description,
131 139 "parents": self.ctx_parents,
132 140 "status": self.ctx_status,
133 141 "_file_paths": self.ctx_list,
134 142 }
135 143
136 144 @reraise_safe_exceptions
137 145 def archive_repo(self, archive_path, mtime, file_info, kind):
138 146 if kind == "tgz":
139 147 archiver = archival.tarit(archive_path, mtime, "gz")
140 148 elif kind == "tbz2":
141 149 archiver = archival.tarit(archive_path, mtime, "bz2")
142 150 elif kind == 'zip':
143 151 archiver = archival.zipit(archive_path, mtime)
144 152 else:
145 153 raise exceptions.ArchiveException(
146 154 'Remote does not support: "%s".' % kind)
147 155
148 156 for f_path, f_mode, f_is_link, f_content in file_info:
149 157 archiver.addfile(f_path, f_mode, f_is_link, f_content)
150 158 archiver.done()
151 159
152 160 @reraise_safe_exceptions
153 161 def bookmarks(self, wire):
154 162 repo = self._factory.repo(wire)
155 163 return dict(repo._bookmarks)
156 164
157 165 @reraise_safe_exceptions
158 166 def branches(self, wire, normal, closed):
159 167 repo = self._factory.repo(wire)
160 168 iter_branches = repo.branchmap().iterbranches()
161 169 bt = {}
162 170 for branch_name, _heads, tip, is_closed in iter_branches:
163 171 if normal and not is_closed:
164 172 bt[branch_name] = tip
165 173 if closed and is_closed:
166 174 bt[branch_name] = tip
167 175
168 176 return bt
169 177
170 178 @reraise_safe_exceptions
171 179 def bulk_request(self, wire, rev, pre_load):
172 180 result = {}
173 181 for attr in pre_load:
174 182 try:
175 183 method = self._bulk_methods[attr]
176 184 result[attr] = method(wire, rev)
177 185 except KeyError:
178 186 raise exceptions.VcsException(
179 187 'Unknown bulk attribute: "%s"' % attr)
180 188 return result
181 189
182 190 @reraise_safe_exceptions
183 191 def clone(self, wire, source, dest, update_after_clone=False, hooks=True):
184 192 baseui = self._factory._create_config(wire["config"], hooks=hooks)
185 193 clone(baseui, source, dest, noupdate=not update_after_clone)
186 194
187 195 @reraise_safe_exceptions
188 196 def commitctx(
189 197 self, wire, message, parents, commit_time, commit_timezone,
190 198 user, files, extra, removed, updated):
191 199
192 200 def _filectxfn(_repo, memctx, path):
193 201 """
194 202 Marks given path as added/changed/removed in a given _repo. This is
195 203 for internal mercurial commit function.
196 204 """
197 205
198 206 # check if this path is removed
199 207 if path in removed:
200 208 # returning None is a way to mark node for removal
201 209 return None
202 210
203 211 # check if this path is added
204 212 for node in updated:
205 213 if node['path'] == path:
206 214 return memfilectx(
207 215 _repo,
208 216 path=node['path'],
209 217 data=node['content'],
210 218 islink=False,
211 219 isexec=bool(node['mode'] & stat.S_IXUSR),
212 220 copied=False,
213 221 memctx=memctx)
214 222
215 223 raise exceptions.AbortException(
216 224 "Given path haven't been marked as added, "
217 225 "changed or removed (%s)" % path)
218 226
219 227 repo = self._factory.repo(wire)
220 228
221 229 commit_ctx = memctx(
222 230 repo=repo,
223 231 parents=parents,
224 232 text=message,
225 233 files=files,
226 234 filectxfn=_filectxfn,
227 235 user=user,
228 236 date=(commit_time, commit_timezone),
229 237 extra=extra)
230 238
231 239 n = repo.commitctx(commit_ctx)
232 240 new_id = hex(n)
233 241
234 242 return new_id
235 243
236 244 @reraise_safe_exceptions
237 245 def ctx_branch(self, wire, revision):
238 246 repo = self._factory.repo(wire)
239 247 ctx = repo[revision]
240 248 return ctx.branch()
241 249
242 250 @reraise_safe_exceptions
243 251 def ctx_children(self, wire, revision):
244 252 repo = self._factory.repo(wire)
245 253 ctx = repo[revision]
246 254 return [child.rev() for child in ctx.children()]
247 255
248 256 @reraise_safe_exceptions
249 257 def ctx_date(self, wire, revision):
250 258 repo = self._factory.repo(wire)
251 259 ctx = repo[revision]
252 260 return ctx.date()
253 261
254 262 @reraise_safe_exceptions
255 263 def ctx_description(self, wire, revision):
256 264 repo = self._factory.repo(wire)
257 265 ctx = repo[revision]
258 266 return ctx.description()
259 267
260 268 @reraise_safe_exceptions
261 269 def ctx_diff(
262 270 self, wire, revision, git=True, ignore_whitespace=True, context=3):
263 271 repo = self._factory.repo(wire)
264 272 ctx = repo[revision]
265 273 result = ctx.diff(
266 274 git=git, ignore_whitespace=ignore_whitespace, context=context)
267 275 return list(result)
268 276
269 277 @reraise_safe_exceptions
270 278 def ctx_files(self, wire, revision):
271 279 repo = self._factory.repo(wire)
272 280 ctx = repo[revision]
273 281 return ctx.files()
274 282
275 283 @reraise_safe_exceptions
276 284 def ctx_list(self, path, revision):
277 285 repo = self._factory.repo(path)
278 286 ctx = repo[revision]
279 287 return list(ctx)
280 288
281 289 @reraise_safe_exceptions
282 290 def ctx_parents(self, wire, revision):
283 291 repo = self._factory.repo(wire)
284 292 ctx = repo[revision]
285 293 return [parent.rev() for parent in ctx.parents()]
286 294
287 295 @reraise_safe_exceptions
288 296 def ctx_substate(self, wire, revision):
289 297 repo = self._factory.repo(wire)
290 298 ctx = repo[revision]
291 299 return ctx.substate
292 300
293 301 @reraise_safe_exceptions
294 302 def ctx_status(self, wire, revision):
295 303 repo = self._factory.repo(wire)
296 304 ctx = repo[revision]
297 305 status = repo[ctx.p1().node()].status(other=ctx.node())
298 306 # object of status (odd, custom named tuple in mercurial) is not
299 307 # correctly serializable via Pyro, we make it a list, as the underling
300 308 # API expects this to be a list
301 309 return list(status)
302 310
303 311 @reraise_safe_exceptions
304 312 def ctx_user(self, wire, revision):
305 313 repo = self._factory.repo(wire)
306 314 ctx = repo[revision]
307 315 return ctx.user()
308 316
309 317 @reraise_safe_exceptions
310 318 def check_url(self, url, config):
311 319 _proto = None
312 320 if '+' in url[:url.find('://')]:
313 321 _proto = url[0:url.find('+')]
314 322 url = url[url.find('+') + 1:]
315 323 handlers = []
316 324 url_obj = hg_url(url)
317 325 test_uri, authinfo = url_obj.authinfo()
318 326 url_obj.passwd = '*****'
319 327 cleaned_uri = str(url_obj)
320 328
321 329 if authinfo:
322 330 # create a password manager
323 331 passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
324 332 passmgr.add_password(*authinfo)
325 333
326 334 handlers.extend((httpbasicauthhandler(passmgr),
327 335 httpdigestauthhandler(passmgr)))
328 336
329 337 o = urllib2.build_opener(*handlers)
330 338 o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
331 339 ('Accept', 'application/mercurial-0.1')]
332 340
333 341 q = {"cmd": 'between'}
334 342 q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)})
335 343 qs = '?%s' % urllib.urlencode(q)
336 344 cu = "%s%s" % (test_uri, qs)
337 345 req = urllib2.Request(cu, None, {})
338 346
339 347 try:
340 348 resp = o.open(req)
341 349 if resp.code != 200:
342 350 raise exceptions.URLError('Return Code is not 200')
343 351 except Exception as e:
344 352 # means it cannot be cloned
345 353 raise exceptions.URLError("[%s] org_exc: %s" % (cleaned_uri, e))
346 354
347 355 # now check if it's a proper hg repo, but don't do it for svn
348 356 try:
349 357 if _proto == 'svn':
350 358 pass
351 359 else:
352 360 # check for pure hg repos
353 361 httppeer(make_ui_from_config(config), url).lookup('tip')
354 362 except Exception as e:
355 363 raise exceptions.URLError(
356 364 "url [%s] does not look like an hg repo org_exc: %s"
357 365 % (cleaned_uri, e))
358 366
359 367 return True
360 368
361 369 @reraise_safe_exceptions
362 370 def diff(
363 371 self, wire, rev1, rev2, file_filter, opt_git, opt_ignorews,
364 372 context):
365 373 repo = self._factory.repo(wire)
366 374
367 375 if file_filter:
368 376 filter = match(file_filter[0], '', [file_filter[1]])
369 377 else:
370 378 filter = file_filter
371 379 opts = diffopts(git=opt_git, ignorews=opt_ignorews, context=context)
372 380
373 381 try:
374 382 return "".join(patch.diff(
375 383 repo, node1=rev1, node2=rev2, match=filter, opts=opts))
376 384 except RepoLookupError:
377 385 raise exceptions.LookupException()
378 386
379 387 @reraise_safe_exceptions
380 388 def file_history(self, wire, revision, path, limit):
381 389 repo = self._factory.repo(wire)
382 390
383 391 ctx = repo[revision]
384 392 fctx = ctx.filectx(path)
385 393
386 394 def history_iter():
387 395 limit_rev = fctx.rev()
388 396 for obj in reversed(list(fctx.filelog())):
389 397 obj = fctx.filectx(obj)
390 398 if limit_rev >= obj.rev():
391 399 yield obj
392 400
393 401 history = []
394 402 for cnt, obj in enumerate(history_iter()):
395 403 if limit and cnt >= limit:
396 404 break
397 405 history.append(hex(obj.node()))
398 406
399 407 return [x for x in history]
400 408
401 409 @reraise_safe_exceptions
402 410 def file_history_untill(self, wire, revision, path, limit):
403 411 repo = self._factory.repo(wire)
404 412 ctx = repo[revision]
405 413 fctx = ctx.filectx(path)
406 414
407 415 file_log = list(fctx.filelog())
408 416 if limit:
409 417 # Limit to the last n items
410 418 file_log = file_log[-limit:]
411 419
412 420 return [hex(fctx.filectx(cs).node()) for cs in reversed(file_log)]
413 421
414 422 @reraise_safe_exceptions
415 423 def fctx_annotate(self, wire, revision, path):
416 424 repo = self._factory.repo(wire)
417 425 ctx = repo[revision]
418 426 fctx = ctx.filectx(path)
419 427
420 428 result = []
421 429 for i, annotate_data in enumerate(fctx.annotate()):
422 430 ln_no = i + 1
423 431 sha = hex(annotate_data[0].node())
424 432 result.append((ln_no, sha, annotate_data[1]))
425 433 return result
426 434
427 435 @reraise_safe_exceptions
428 436 def fctx_data(self, wire, revision, path):
429 437 repo = self._factory.repo(wire)
430 438 ctx = repo[revision]
431 439 fctx = ctx.filectx(path)
432 440 return fctx.data()
433 441
434 442 @reraise_safe_exceptions
435 443 def fctx_flags(self, wire, revision, path):
436 444 repo = self._factory.repo(wire)
437 445 ctx = repo[revision]
438 446 fctx = ctx.filectx(path)
439 447 return fctx.flags()
440 448
441 449 @reraise_safe_exceptions
442 450 def fctx_size(self, wire, revision, path):
443 451 repo = self._factory.repo(wire)
444 452 ctx = repo[revision]
445 453 fctx = ctx.filectx(path)
446 454 return fctx.size()
447 455
448 456 @reraise_safe_exceptions
449 457 def get_all_commit_ids(self, wire, name):
450 458 repo = self._factory.repo(wire)
451 459 revs = repo.filtered(name).changelog.index
452 460 return map(lambda x: hex(x[7]), revs)[:-1]
453 461
454 462 @reraise_safe_exceptions
455 463 def get_config_value(self, wire, section, name, untrusted=False):
456 464 repo = self._factory.repo(wire)
457 465 return repo.ui.config(section, name, untrusted=untrusted)
458 466
459 467 @reraise_safe_exceptions
460 468 def get_config_bool(self, wire, section, name, untrusted=False):
461 469 repo = self._factory.repo(wire)
462 470 return repo.ui.configbool(section, name, untrusted=untrusted)
463 471
464 472 @reraise_safe_exceptions
465 473 def get_config_list(self, wire, section, name, untrusted=False):
466 474 repo = self._factory.repo(wire)
467 475 return repo.ui.configlist(section, name, untrusted=untrusted)
468 476
469 477 @reraise_safe_exceptions
470 478 def is_large_file(self, wire, path):
471 479 return largefiles.lfutil.isstandin(path)
472 480
473 481 @reraise_safe_exceptions
474 482 def in_store(self, wire, sha):
475 483 repo = self._factory.repo(wire)
476 484 return largefiles.lfutil.instore(repo, sha)
477 485
478 486 @reraise_safe_exceptions
479 487 def in_user_cache(self, wire, sha):
480 488 repo = self._factory.repo(wire)
481 489 return largefiles.lfutil.inusercache(repo.ui, sha)
482 490
483 491 @reraise_safe_exceptions
484 492 def store_path(self, wire, sha):
485 493 repo = self._factory.repo(wire)
486 494 return largefiles.lfutil.storepath(repo, sha)
487 495
488 496 @reraise_safe_exceptions
489 497 def link(self, wire, sha, path):
490 498 repo = self._factory.repo(wire)
491 499 largefiles.lfutil.link(
492 500 largefiles.lfutil.usercachepath(repo.ui, sha), path)
493 501
494 502 @reraise_safe_exceptions
495 503 def localrepository(self, wire, create=False):
496 504 self._factory.repo(wire, create=create)
497 505
498 506 @reraise_safe_exceptions
499 507 def lookup(self, wire, revision, both):
500 508 # TODO Paris: Ugly hack to "deserialize" long for msgpack
501 509 if isinstance(revision, float):
502 510 revision = long(revision)
503 511 repo = self._factory.repo(wire)
504 512 try:
505 513 ctx = repo[revision]
506 514 except RepoLookupError:
507 515 raise exceptions.LookupException(revision)
508 516 except LookupError as e:
509 517 raise exceptions.LookupException(e.name)
510 518
511 519 if not both:
512 520 return ctx.hex()
513 521
514 522 ctx = repo[ctx.hex()]
515 523 return ctx.hex(), ctx.rev()
516 524
517 525 @reraise_safe_exceptions
518 526 def pull(self, wire, url, commit_ids=None):
519 527 repo = self._factory.repo(wire)
520 528 remote = peer(repo, {}, url)
521 529 if commit_ids:
522 530 commit_ids = [bin(commit_id) for commit_id in commit_ids]
523 531
524 532 return exchange.pull(
525 533 repo, remote, heads=commit_ids, force=None).cgresult
526 534
527 535 @reraise_safe_exceptions
528 536 def revision(self, wire, rev):
529 537 repo = self._factory.repo(wire)
530 538 ctx = repo[rev]
531 539 return ctx.rev()
532 540
533 541 @reraise_safe_exceptions
534 542 def rev_range(self, wire, filter):
535 543 repo = self._factory.repo(wire)
536 544 revisions = [rev for rev in revrange(repo, filter)]
537 545 return revisions
538 546
539 547 @reraise_safe_exceptions
540 548 def rev_range_hash(self, wire, node):
541 549 repo = self._factory.repo(wire)
542 550
543 551 def get_revs(repo, rev_opt):
544 552 if rev_opt:
545 553 revs = revrange(repo, rev_opt)
546 554 if len(revs) == 0:
547 555 return (nullrev, nullrev)
548 556 return max(revs), min(revs)
549 557 else:
550 558 return len(repo) - 1, 0
551 559
552 560 stop, start = get_revs(repo, [node + ':'])
553 561 revs = [hex(repo[r].node()) for r in xrange(start, stop + 1)]
554 562 return revs
555 563
556 564 @reraise_safe_exceptions
557 565 def revs_from_revspec(self, wire, rev_spec, *args, **kwargs):
558 566 other_path = kwargs.pop('other_path', None)
559 567
560 568 # case when we want to compare two independent repositories
561 569 if other_path and other_path != wire["path"]:
562 570 baseui = self._factory._create_config(wire["config"])
563 571 repo = unionrepo.unionrepository(baseui, other_path, wire["path"])
564 572 else:
565 573 repo = self._factory.repo(wire)
566 574 return list(repo.revs(rev_spec, *args))
567 575
568 576 @reraise_safe_exceptions
569 577 def strip(self, wire, revision, update, backup):
570 578 repo = self._factory.repo(wire)
571 579 ctx = repo[revision]
572 580 hgext_strip(
573 581 repo.baseui, repo, ctx.node(), update=update, backup=backup)
574 582
575 583 @reraise_safe_exceptions
576 584 def tag(self, wire, name, revision, message, local, user,
577 585 tag_time, tag_timezone):
578 586 repo = self._factory.repo(wire)
579 587 ctx = repo[revision]
580 588 node = ctx.node()
581 589
582 590 date = (tag_time, tag_timezone)
583 591 try:
584 592 repo.tag(name, node, message, local, user, date)
585 593 except Abort:
586 594 log.exception("Tag operation aborted")
587 595 raise exceptions.AbortException()
588 596
589 597 @reraise_safe_exceptions
590 598 def tags(self, wire):
591 599 repo = self._factory.repo(wire)
592 600 return repo.tags()
593 601
594 602 @reraise_safe_exceptions
595 603 def update(self, wire, node=None, clean=False):
596 604 repo = self._factory.repo(wire)
597 605 baseui = self._factory._create_config(wire['config'])
598 606 commands.update(baseui, repo, node=node, clean=clean)
599 607
600 608 @reraise_safe_exceptions
601 609 def identify(self, wire):
602 610 repo = self._factory.repo(wire)
603 611 baseui = self._factory._create_config(wire['config'])
604 612 output = io.BytesIO()
605 613 baseui.write = output.write
606 614 # This is required to get a full node id
607 615 baseui.debugflag = True
608 616 commands.identify(baseui, repo, id=True)
609 617
610 618 return output.getvalue()
611 619
612 620 @reraise_safe_exceptions
613 621 def pull_cmd(self, wire, source, bookmark=None, branch=None, revision=None,
614 622 hooks=True):
615 623 repo = self._factory.repo(wire)
616 624 baseui = self._factory._create_config(wire['config'], hooks=hooks)
617 625
618 626 # Mercurial internally has a lot of logic that checks ONLY if
619 627 # option is defined, we just pass those if they are defined then
620 628 opts = {}
621 629 if bookmark:
622 630 opts['bookmark'] = bookmark
623 631 if branch:
624 632 opts['branch'] = branch
625 633 if revision:
626 634 opts['rev'] = revision
627 635
628 636 commands.pull(baseui, repo, source, **opts)
629 637
630 638 @reraise_safe_exceptions
631 639 def heads(self, wire, branch=None):
632 640 repo = self._factory.repo(wire)
633 641 baseui = self._factory._create_config(wire['config'])
634 642 output = io.BytesIO()
635 643
636 644 def write(data, **unused_kwargs):
637 645 output.write(data)
638 646
639 647 baseui.write = write
640 648 if branch:
641 649 args = [branch]
642 650 else:
643 651 args = []
644 652 commands.heads(baseui, repo, template='{node} ', *args)
645 653
646 654 return output.getvalue()
647 655
648 656 @reraise_safe_exceptions
649 657 def ancestor(self, wire, revision1, revision2):
650 658 repo = self._factory.repo(wire)
651 659 baseui = self._factory._create_config(wire['config'])
652 660 output = io.BytesIO()
653 661 baseui.write = output.write
654 662 commands.debugancestor(baseui, repo, revision1, revision2)
655 663
656 664 return output.getvalue()
657 665
658 666 @reraise_safe_exceptions
659 667 def push(self, wire, revisions, dest_path, hooks=True,
660 668 push_branches=False):
661 669 repo = self._factory.repo(wire)
662 670 baseui = self._factory._create_config(wire['config'], hooks=hooks)
663 671 commands.push(baseui, repo, dest=dest_path, rev=revisions,
664 672 new_branch=push_branches)
665 673
666 674 @reraise_safe_exceptions
667 675 def merge(self, wire, revision):
668 676 repo = self._factory.repo(wire)
669 677 baseui = self._factory._create_config(wire['config'])
670 678 repo.ui.setconfig('ui', 'merge', 'internal:dump')
671 679 commands.merge(baseui, repo, rev=revision)
672 680
673 681 @reraise_safe_exceptions
674 682 def commit(self, wire, message, username):
675 683 repo = self._factory.repo(wire)
676 684 baseui = self._factory._create_config(wire['config'])
677 685 repo.ui.setconfig('ui', 'username', username)
678 686 commands.commit(baseui, repo, message=message)
679 687
680 688 @reraise_safe_exceptions
681 689 def rebase(self, wire, source=None, dest=None, abort=False):
682 690 repo = self._factory.repo(wire)
683 691 baseui = self._factory._create_config(wire['config'])
684 692 repo.ui.setconfig('ui', 'merge', 'internal:dump')
685 693 rebase.rebase(
686 694 baseui, repo, base=source, dest=dest, abort=abort, keep=not abort)
687 695
688 696 @reraise_safe_exceptions
689 697 def bookmark(self, wire, bookmark, revision=None):
690 698 repo = self._factory.repo(wire)
691 699 baseui = self._factory._create_config(wire['config'])
692 700 commands.bookmark(baseui, repo, bookmark, rev=revision, force=True)
General Comments 0
You need to be logged in to leave comments. Login now