##// END OF EJS Templates
clone: use `exchange.push` instead of `localrepo.push`...
Pierre-Yves David -
r22618:ce95c15f default
parent child Browse files
Show More
@@ -1,679 +1,679 b''
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 from i18n import _
10 10 from lock import release
11 11 from node import hex, nullid
12 12 import localrepo, bundlerepo, unionrepo, httppeer, sshpeer, statichttprepo
13 13 import bookmarks, lock, util, extensions, error, node, scmutil, phases, url
14 import cmdutil, discovery, repoview
14 import cmdutil, discovery, repoview, exchange
15 15 import merge as mergemod
16 16 import verify as verifymod
17 17 import errno, os, shutil
18 18
19 19 def _local(path):
20 20 path = util.expandpath(util.urllocalpath(path))
21 21 return (os.path.isfile(path) and bundlerepo or localrepo)
22 22
23 23 def addbranchrevs(lrepo, other, branches, revs):
24 24 peer = other.peer() # a courtesy to callers using a localrepo for other
25 25 hashbranch, branches = branches
26 26 if not hashbranch and not branches:
27 27 return revs or None, revs and revs[0] or None
28 28 revs = revs and list(revs) or []
29 29 if not peer.capable('branchmap'):
30 30 if branches:
31 31 raise util.Abort(_("remote branch lookup not supported"))
32 32 revs.append(hashbranch)
33 33 return revs, revs[0]
34 34 branchmap = peer.branchmap()
35 35
36 36 def primary(branch):
37 37 if branch == '.':
38 38 if not lrepo:
39 39 raise util.Abort(_("dirstate branch not accessible"))
40 40 branch = lrepo.dirstate.branch()
41 41 if branch in branchmap:
42 42 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
43 43 return True
44 44 else:
45 45 return False
46 46
47 47 for branch in branches:
48 48 if not primary(branch):
49 49 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
50 50 if hashbranch:
51 51 if not primary(hashbranch):
52 52 revs.append(hashbranch)
53 53 return revs, revs[0]
54 54
55 55 def parseurl(path, branches=None):
56 56 '''parse url#branch, returning (url, (branch, branches))'''
57 57
58 58 u = util.url(path)
59 59 branch = None
60 60 if u.fragment:
61 61 branch = u.fragment
62 62 u.fragment = None
63 63 return str(u), (branch, branches or [])
64 64
65 65 schemes = {
66 66 'bundle': bundlerepo,
67 67 'union': unionrepo,
68 68 'file': _local,
69 69 'http': httppeer,
70 70 'https': httppeer,
71 71 'ssh': sshpeer,
72 72 'static-http': statichttprepo,
73 73 }
74 74
75 75 def _peerlookup(path):
76 76 u = util.url(path)
77 77 scheme = u.scheme or 'file'
78 78 thing = schemes.get(scheme) or schemes['file']
79 79 try:
80 80 return thing(path)
81 81 except TypeError:
82 82 return thing
83 83
84 84 def islocal(repo):
85 85 '''return true if repo (or path pointing to repo) is local'''
86 86 if isinstance(repo, str):
87 87 try:
88 88 return _peerlookup(repo).islocal(repo)
89 89 except AttributeError:
90 90 return False
91 91 return repo.local()
92 92
93 93 def openpath(ui, path):
94 94 '''open path with open if local, url.open if remote'''
95 95 pathurl = util.url(path, parsequery=False, parsefragment=False)
96 96 if pathurl.islocal():
97 97 return util.posixfile(pathurl.localpath(), 'rb')
98 98 else:
99 99 return url.open(ui, path)
100 100
101 101 # a list of (ui, repo) functions called for wire peer initialization
102 102 wirepeersetupfuncs = []
103 103
104 104 def _peerorrepo(ui, path, create=False):
105 105 """return a repository object for the specified path"""
106 106 obj = _peerlookup(path).instance(ui, path, create)
107 107 ui = getattr(obj, "ui", ui)
108 108 for name, module in extensions.extensions(ui):
109 109 hook = getattr(module, 'reposetup', None)
110 110 if hook:
111 111 hook(ui, obj)
112 112 if not obj.local():
113 113 for f in wirepeersetupfuncs:
114 114 f(ui, obj)
115 115 return obj
116 116
117 117 def repository(ui, path='', create=False):
118 118 """return a repository object for the specified path"""
119 119 peer = _peerorrepo(ui, path, create)
120 120 repo = peer.local()
121 121 if not repo:
122 122 raise util.Abort(_("repository '%s' is not local") %
123 123 (path or peer.url()))
124 124 return repo.filtered('visible')
125 125
126 126 def peer(uiorrepo, opts, path, create=False):
127 127 '''return a repository peer for the specified path'''
128 128 rui = remoteui(uiorrepo, opts)
129 129 return _peerorrepo(rui, path, create).peer()
130 130
131 131 def defaultdest(source):
132 132 '''return default destination of clone if none is given
133 133
134 134 >>> defaultdest('foo')
135 135 'foo'
136 136 >>> defaultdest('/foo/bar')
137 137 'bar'
138 138 >>> defaultdest('/')
139 139 ''
140 140 >>> defaultdest('')
141 141 ''
142 142 >>> defaultdest('http://example.org/')
143 143 ''
144 144 >>> defaultdest('http://example.org/foo/')
145 145 'foo'
146 146 '''
147 147 path = util.url(source).path
148 148 if not path:
149 149 return ''
150 150 return os.path.basename(os.path.normpath(path))
151 151
152 152 def share(ui, source, dest=None, update=True):
153 153 '''create a shared repository'''
154 154
155 155 if not islocal(source):
156 156 raise util.Abort(_('can only share local repositories'))
157 157
158 158 if not dest:
159 159 dest = defaultdest(source)
160 160 else:
161 161 dest = ui.expandpath(dest)
162 162
163 163 if isinstance(source, str):
164 164 origsource = ui.expandpath(source)
165 165 source, branches = parseurl(origsource)
166 166 srcrepo = repository(ui, source)
167 167 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
168 168 else:
169 169 srcrepo = source.local()
170 170 origsource = source = srcrepo.url()
171 171 checkout = None
172 172
173 173 sharedpath = srcrepo.sharedpath # if our source is already sharing
174 174
175 175 destwvfs = scmutil.vfs(dest, realpath=True)
176 176 destvfs = scmutil.vfs(os.path.join(destwvfs.base, '.hg'), realpath=True)
177 177
178 178 if destvfs.lexists():
179 179 raise util.Abort(_('destination already exists'))
180 180
181 181 if not destwvfs.isdir():
182 182 destwvfs.mkdir()
183 183 destvfs.makedir()
184 184
185 185 requirements = ''
186 186 try:
187 187 requirements = srcrepo.opener.read('requires')
188 188 except IOError, inst:
189 189 if inst.errno != errno.ENOENT:
190 190 raise
191 191
192 192 requirements += 'shared\n'
193 193 destvfs.write('requires', requirements)
194 194 destvfs.write('sharedpath', sharedpath)
195 195
196 196 r = repository(ui, destwvfs.base)
197 197
198 198 default = srcrepo.ui.config('paths', 'default')
199 199 if default:
200 200 fp = r.opener("hgrc", "w", text=True)
201 201 fp.write("[paths]\n")
202 202 fp.write("default = %s\n" % default)
203 203 fp.close()
204 204
205 205 if update:
206 206 r.ui.status(_("updating working directory\n"))
207 207 if update is not True:
208 208 checkout = update
209 209 for test in (checkout, 'default', 'tip'):
210 210 if test is None:
211 211 continue
212 212 try:
213 213 uprev = r.lookup(test)
214 214 break
215 215 except error.RepoLookupError:
216 216 continue
217 217 _update(r, uprev)
218 218
219 219 def copystore(ui, srcrepo, destpath):
220 220 '''copy files from store of srcrepo in destpath
221 221
222 222 returns destlock
223 223 '''
224 224 destlock = None
225 225 try:
226 226 hardlink = None
227 227 num = 0
228 228 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
229 229 srcvfs = scmutil.vfs(srcrepo.sharedpath)
230 230 dstvfs = scmutil.vfs(destpath)
231 231 for f in srcrepo.store.copylist():
232 232 if srcpublishing and f.endswith('phaseroots'):
233 233 continue
234 234 dstbase = os.path.dirname(f)
235 235 if dstbase and not dstvfs.exists(dstbase):
236 236 dstvfs.mkdir(dstbase)
237 237 if srcvfs.exists(f):
238 238 if f.endswith('data'):
239 239 # 'dstbase' may be empty (e.g. revlog format 0)
240 240 lockfile = os.path.join(dstbase, "lock")
241 241 # lock to avoid premature writing to the target
242 242 destlock = lock.lock(dstvfs, lockfile)
243 243 hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
244 244 hardlink)
245 245 num += n
246 246 if hardlink:
247 247 ui.debug("linked %d files\n" % num)
248 248 else:
249 249 ui.debug("copied %d files\n" % num)
250 250 return destlock
251 251 except: # re-raises
252 252 release(destlock)
253 253 raise
254 254
255 255 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
256 256 update=True, stream=False, branch=None):
257 257 """Make a copy of an existing repository.
258 258
259 259 Create a copy of an existing repository in a new directory. The
260 260 source and destination are URLs, as passed to the repository
261 261 function. Returns a pair of repository peers, the source and
262 262 newly created destination.
263 263
264 264 The location of the source is added to the new repository's
265 265 .hg/hgrc file, as the default to be used for future pulls and
266 266 pushes.
267 267
268 268 If an exception is raised, the partly cloned/updated destination
269 269 repository will be deleted.
270 270
271 271 Arguments:
272 272
273 273 source: repository object or URL
274 274
275 275 dest: URL of destination repository to create (defaults to base
276 276 name of source repository)
277 277
278 278 pull: always pull from source repository, even in local case
279 279
280 280 stream: stream raw data uncompressed from repository (fast over
281 281 LAN, slow over WAN)
282 282
283 283 rev: revision to clone up to (implies pull=True)
284 284
285 285 update: update working directory after clone completes, if
286 286 destination is local repository (True means update to default rev,
287 287 anything else is treated as a revision)
288 288
289 289 branch: branches to clone
290 290 """
291 291
292 292 if isinstance(source, str):
293 293 origsource = ui.expandpath(source)
294 294 source, branch = parseurl(origsource, branch)
295 295 srcpeer = peer(ui, peeropts, source)
296 296 else:
297 297 srcpeer = source.peer() # in case we were called with a localrepo
298 298 branch = (None, branch or [])
299 299 origsource = source = srcpeer.url()
300 300 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
301 301
302 302 if dest is None:
303 303 dest = defaultdest(source)
304 304 if dest:
305 305 ui.status(_("destination directory: %s\n") % dest)
306 306 else:
307 307 dest = ui.expandpath(dest)
308 308
309 309 dest = util.urllocalpath(dest)
310 310 source = util.urllocalpath(source)
311 311
312 312 if not dest:
313 313 raise util.Abort(_("empty destination path is not valid"))
314 314
315 315 destvfs = scmutil.vfs(dest, expandpath=True)
316 316 if destvfs.lexists():
317 317 if not destvfs.isdir():
318 318 raise util.Abort(_("destination '%s' already exists") % dest)
319 319 elif destvfs.listdir():
320 320 raise util.Abort(_("destination '%s' is not empty") % dest)
321 321
322 322 srclock = destlock = cleandir = None
323 323 srcrepo = srcpeer.local()
324 324 try:
325 325 abspath = origsource
326 326 if islocal(origsource):
327 327 abspath = os.path.abspath(util.urllocalpath(origsource))
328 328
329 329 if islocal(dest):
330 330 cleandir = dest
331 331
332 332 copy = False
333 333 if (srcrepo and srcrepo.cancopy() and islocal(dest)
334 334 and not phases.hassecret(srcrepo)):
335 335 copy = not pull and not rev
336 336
337 337 if copy:
338 338 try:
339 339 # we use a lock here because if we race with commit, we
340 340 # can end up with extra data in the cloned revlogs that's
341 341 # not pointed to by changesets, thus causing verify to
342 342 # fail
343 343 srclock = srcrepo.lock(wait=False)
344 344 except error.LockError:
345 345 copy = False
346 346
347 347 if copy:
348 348 srcrepo.hook('preoutgoing', throw=True, source='clone')
349 349 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
350 350 if not os.path.exists(dest):
351 351 os.mkdir(dest)
352 352 else:
353 353 # only clean up directories we create ourselves
354 354 cleandir = hgdir
355 355 try:
356 356 destpath = hgdir
357 357 util.makedir(destpath, notindexed=True)
358 358 except OSError, inst:
359 359 if inst.errno == errno.EEXIST:
360 360 cleandir = None
361 361 raise util.Abort(_("destination '%s' already exists")
362 362 % dest)
363 363 raise
364 364
365 365 destlock = copystore(ui, srcrepo, destpath)
366 366
367 367 # Recomputing branch cache might be slow on big repos,
368 368 # so just copy it
369 369 def copybranchcache(fname):
370 370 srcbranchcache = srcrepo.join('cache/%s' % fname)
371 371 dstbranchcache = os.path.join(dstcachedir, fname)
372 372 if os.path.exists(srcbranchcache):
373 373 if not os.path.exists(dstcachedir):
374 374 os.mkdir(dstcachedir)
375 375 util.copyfile(srcbranchcache, dstbranchcache)
376 376
377 377 dstcachedir = os.path.join(destpath, 'cache')
378 378 # In local clones we're copying all nodes, not just served
379 379 # ones. Therefore copy all branchcaches over.
380 380 copybranchcache('branch2')
381 381 for cachename in repoview.filtertable:
382 382 copybranchcache('branch2-%s' % cachename)
383 383
384 384 # we need to re-init the repo after manually copying the data
385 385 # into it
386 386 destpeer = peer(srcrepo, peeropts, dest)
387 387 srcrepo.hook('outgoing', source='clone',
388 388 node=node.hex(node.nullid))
389 389 else:
390 390 try:
391 391 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
392 392 # only pass ui when no srcrepo
393 393 except OSError, inst:
394 394 if inst.errno == errno.EEXIST:
395 395 cleandir = None
396 396 raise util.Abort(_("destination '%s' already exists")
397 397 % dest)
398 398 raise
399 399
400 400 revs = None
401 401 if rev:
402 402 if not srcpeer.capable('lookup'):
403 403 raise util.Abort(_("src repository does not support "
404 404 "revision lookup and so doesn't "
405 405 "support clone by revision"))
406 406 revs = [srcpeer.lookup(r) for r in rev]
407 407 checkout = revs[0]
408 408 if destpeer.local():
409 409 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
410 410 elif srcrepo:
411 srcrepo.push(destpeer, revs=revs)
411 exchange.push(srcrepo, destpeer, revs=revs)
412 412 else:
413 413 raise util.Abort(_("clone from remote to remote not supported"))
414 414
415 415 cleandir = None
416 416
417 417 # clone all bookmarks except divergent ones
418 418 destrepo = destpeer.local()
419 419 if destrepo and srcpeer.capable("pushkey"):
420 420 rb = srcpeer.listkeys('bookmarks')
421 421 marks = destrepo._bookmarks
422 422 for k, n in rb.iteritems():
423 423 try:
424 424 m = destrepo.lookup(n)
425 425 marks[k] = m
426 426 except error.RepoLookupError:
427 427 pass
428 428 if rb:
429 429 marks.write()
430 430 elif srcrepo and destpeer.capable("pushkey"):
431 431 for k, n in srcrepo._bookmarks.iteritems():
432 432 destpeer.pushkey('bookmarks', k, '', hex(n))
433 433
434 434 if destrepo:
435 435 template = (
436 436 '# You may want to set your username here if it is not set\n'
437 437 "# globally, or this repository requires a different\n"
438 438 '# username from your usual configuration. If you want to\n'
439 439 '# set something for all of your repositories on this\n'
440 440 '# computer, try running the command\n'
441 441 "# 'hg config --edit --global'\n"
442 442 '# [ui]\n'
443 443 '# username = Jane Doe <jdoe@example.com>\n'
444 444 '[paths]\n'
445 445 'default = %s\n'
446 446 )
447 447 fp = destrepo.opener("hgrc", "w", text=True)
448 448 u = util.url(abspath)
449 449 u.passwd = None
450 450 defaulturl = str(u)
451 451 fp.write(template % defaulturl)
452 452 fp.close()
453 453
454 454 destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone')
455 455
456 456 if update:
457 457 if update is not True:
458 458 checkout = srcpeer.lookup(update)
459 459 uprev = None
460 460 status = None
461 461 if checkout is not None:
462 462 try:
463 463 uprev = destrepo.lookup(checkout)
464 464 except error.RepoLookupError:
465 465 pass
466 466 if uprev is None:
467 467 try:
468 468 uprev = destrepo._bookmarks['@']
469 469 update = '@'
470 470 bn = destrepo[uprev].branch()
471 471 if bn == 'default':
472 472 status = _("updating to bookmark @\n")
473 473 else:
474 474 status = (_("updating to bookmark @ on branch %s\n")
475 475 % bn)
476 476 except KeyError:
477 477 try:
478 478 uprev = destrepo.branchtip('default')
479 479 except error.RepoLookupError:
480 480 uprev = destrepo.lookup('tip')
481 481 if not status:
482 482 bn = destrepo[uprev].branch()
483 483 status = _("updating to branch %s\n") % bn
484 484 destrepo.ui.status(status)
485 485 _update(destrepo, uprev)
486 486 if update in destrepo._bookmarks:
487 487 bookmarks.setcurrent(destrepo, update)
488 488 finally:
489 489 release(srclock, destlock)
490 490 if cleandir is not None:
491 491 shutil.rmtree(cleandir, True)
492 492 if srcpeer is not None:
493 493 srcpeer.close()
494 494 return srcpeer, destpeer
495 495
496 496 def _showstats(repo, stats):
497 497 repo.ui.status(_("%d files updated, %d files merged, "
498 498 "%d files removed, %d files unresolved\n") % stats)
499 499
500 500 def updaterepo(repo, node, overwrite):
501 501 """Update the working directory to node.
502 502
503 503 When overwrite is set, changes are clobbered, merged else
504 504
505 505 returns stats (see pydoc mercurial.merge.applyupdates)"""
506 506 return mergemod.update(repo, node, False, overwrite, None,
507 507 labels=['working copy', 'destination'])
508 508
509 509 def update(repo, node):
510 510 """update the working directory to node, merging linear changes"""
511 511 stats = updaterepo(repo, node, False)
512 512 _showstats(repo, stats)
513 513 if stats[3]:
514 514 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
515 515 return stats[3] > 0
516 516
517 517 # naming conflict in clone()
518 518 _update = update
519 519
520 520 def clean(repo, node, show_stats=True):
521 521 """forcibly switch the working directory to node, clobbering changes"""
522 522 stats = updaterepo(repo, node, True)
523 523 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
524 524 if show_stats:
525 525 _showstats(repo, stats)
526 526 return stats[3] > 0
527 527
528 528 def merge(repo, node, force=None, remind=True):
529 529 """Branch merge with node, resolving changes. Return true if any
530 530 unresolved conflicts."""
531 531 stats = mergemod.update(repo, node, True, force, False)
532 532 _showstats(repo, stats)
533 533 if stats[3]:
534 534 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
535 535 "or 'hg update -C .' to abandon\n"))
536 536 elif remind:
537 537 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
538 538 return stats[3] > 0
539 539
540 540 def _incoming(displaychlist, subreporecurse, ui, repo, source,
541 541 opts, buffered=False):
542 542 """
543 543 Helper for incoming / gincoming.
544 544 displaychlist gets called with
545 545 (remoterepo, incomingchangesetlist, displayer) parameters,
546 546 and is supposed to contain only code that can't be unified.
547 547 """
548 548 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
549 549 other = peer(repo, opts, source)
550 550 ui.status(_('comparing with %s\n') % util.hidepassword(source))
551 551 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
552 552
553 553 if revs:
554 554 revs = [other.lookup(rev) for rev in revs]
555 555 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
556 556 revs, opts["bundle"], opts["force"])
557 557 try:
558 558 if not chlist:
559 559 ui.status(_("no changes found\n"))
560 560 return subreporecurse()
561 561
562 562 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
563 563 displaychlist(other, chlist, displayer)
564 564 displayer.close()
565 565 finally:
566 566 cleanupfn()
567 567 subreporecurse()
568 568 return 0 # exit code is zero since we found incoming changes
569 569
570 570 def incoming(ui, repo, source, opts):
571 571 def subreporecurse():
572 572 ret = 1
573 573 if opts.get('subrepos'):
574 574 ctx = repo[None]
575 575 for subpath in sorted(ctx.substate):
576 576 sub = ctx.sub(subpath)
577 577 ret = min(ret, sub.incoming(ui, source, opts))
578 578 return ret
579 579
580 580 def display(other, chlist, displayer):
581 581 limit = cmdutil.loglimit(opts)
582 582 if opts.get('newest_first'):
583 583 chlist.reverse()
584 584 count = 0
585 585 for n in chlist:
586 586 if limit is not None and count >= limit:
587 587 break
588 588 parents = [p for p in other.changelog.parents(n) if p != nullid]
589 589 if opts.get('no_merges') and len(parents) == 2:
590 590 continue
591 591 count += 1
592 592 displayer.show(other[n])
593 593 return _incoming(display, subreporecurse, ui, repo, source, opts)
594 594
595 595 def _outgoing(ui, repo, dest, opts):
596 596 dest = ui.expandpath(dest or 'default-push', dest or 'default')
597 597 dest, branches = parseurl(dest, opts.get('branch'))
598 598 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
599 599 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
600 600 if revs:
601 601 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
602 602
603 603 other = peer(repo, opts, dest)
604 604 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
605 605 force=opts.get('force'))
606 606 o = outgoing.missing
607 607 if not o:
608 608 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
609 609 return o, other
610 610
611 611 def outgoing(ui, repo, dest, opts):
612 612 def recurse():
613 613 ret = 1
614 614 if opts.get('subrepos'):
615 615 ctx = repo[None]
616 616 for subpath in sorted(ctx.substate):
617 617 sub = ctx.sub(subpath)
618 618 ret = min(ret, sub.outgoing(ui, dest, opts))
619 619 return ret
620 620
621 621 limit = cmdutil.loglimit(opts)
622 622 o, other = _outgoing(ui, repo, dest, opts)
623 623 if not o:
624 624 cmdutil.outgoinghooks(ui, repo, other, opts, o)
625 625 return recurse()
626 626
627 627 if opts.get('newest_first'):
628 628 o.reverse()
629 629 displayer = cmdutil.show_changeset(ui, repo, opts)
630 630 count = 0
631 631 for n in o:
632 632 if limit is not None and count >= limit:
633 633 break
634 634 parents = [p for p in repo.changelog.parents(n) if p != nullid]
635 635 if opts.get('no_merges') and len(parents) == 2:
636 636 continue
637 637 count += 1
638 638 displayer.show(repo[n])
639 639 displayer.close()
640 640 cmdutil.outgoinghooks(ui, repo, other, opts, o)
641 641 recurse()
642 642 return 0 # exit code is zero since we found outgoing changes
643 643
644 644 def revert(repo, node, choose):
645 645 """revert changes to revision in node without updating dirstate"""
646 646 return mergemod.update(repo, node, False, True, choose)[3] > 0
647 647
648 648 def verify(repo):
649 649 """verify the consistency of a repository"""
650 650 return verifymod.verify(repo)
651 651
652 652 def remoteui(src, opts):
653 653 'build a remote ui from ui or repo and opts'
654 654 if util.safehasattr(src, 'baseui'): # looks like a repository
655 655 dst = src.baseui.copy() # drop repo-specific config
656 656 src = src.ui # copy target options from repo
657 657 else: # assume it's a global ui object
658 658 dst = src.copy() # keep all global options
659 659
660 660 # copy ssh-specific options
661 661 for o in 'ssh', 'remotecmd':
662 662 v = opts.get(o) or src.config('ui', o)
663 663 if v:
664 664 dst.setconfig("ui", o, v, 'copied')
665 665
666 666 # copy bundle-specific options
667 667 r = src.config('bundle', 'mainreporoot')
668 668 if r:
669 669 dst.setconfig('bundle', 'mainreporoot', r, 'copied')
670 670
671 671 # copy selected local settings to the remote ui
672 672 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
673 673 for key, val in src.configitems(sect):
674 674 dst.setconfig(sect, key, val, 'copied')
675 675 v = src.config('web', 'cacerts')
676 676 if v:
677 677 dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
678 678
679 679 return dst
General Comments 0
You need to be logged in to leave comments. Login now