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