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