##// END OF EJS Templates
hg: update to use vfs functions in shared destination repository...
Chinmay Joshi -
r21801:2ccd71bb default
parent child Browse files
Show More
@@ -1,660 +1,661 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 14 import cmdutil, discovery
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 root = os.path.realpath(dest)
176 176 roothg = os.path.join(root, '.hg')
177 177 destwvfs = scmutil.vfs(dest, realpath=True)
178 destvfs = scmutil.vfs(os.path.join(destwvfs.base, '.hg'), realpath=True)
178 179
179 if os.path.exists(roothg):
180 if destvfs.lexists():
180 181 raise util.Abort(_('destination already exists'))
181 182
182 183 if not destwvfs.isdir():
183 184 destwvfs.mkdir()
184 util.makedir(roothg, notindexed=True)
185 destvfs.makedir()
185 186
186 187 requirements = ''
187 188 try:
188 189 requirements = srcrepo.opener.read('requires')
189 190 except IOError, inst:
190 191 if inst.errno != errno.ENOENT:
191 192 raise
192 193
193 194 requirements += 'shared\n'
194 195 util.writefile(os.path.join(roothg, 'requires'), requirements)
195 196 util.writefile(os.path.join(roothg, 'sharedpath'), sharedpath)
196 197
197 198 r = repository(ui, destwvfs.base)
198 199
199 200 default = srcrepo.ui.config('paths', 'default')
200 201 if default:
201 202 fp = r.opener("hgrc", "w", text=True)
202 203 fp.write("[paths]\n")
203 204 fp.write("default = %s\n" % default)
204 205 fp.close()
205 206
206 207 if update:
207 208 r.ui.status(_("updating working directory\n"))
208 209 if update is not True:
209 210 checkout = update
210 211 for test in (checkout, 'default', 'tip'):
211 212 if test is None:
212 213 continue
213 214 try:
214 215 uprev = r.lookup(test)
215 216 break
216 217 except error.RepoLookupError:
217 218 continue
218 219 _update(r, uprev)
219 220
220 221 def copystore(ui, srcrepo, destpath):
221 222 '''copy files from store of srcrepo in destpath
222 223
223 224 returns destlock
224 225 '''
225 226 destlock = None
226 227 try:
227 228 hardlink = None
228 229 num = 0
229 230 srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
230 231 srcvfs = scmutil.vfs(srcrepo.sharedpath)
231 232 dstvfs = scmutil.vfs(destpath)
232 233 for f in srcrepo.store.copylist():
233 234 if srcpublishing and f.endswith('phaseroots'):
234 235 continue
235 236 dstbase = os.path.dirname(f)
236 237 if dstbase and not dstvfs.exists(dstbase):
237 238 dstvfs.mkdir(dstbase)
238 239 if srcvfs.exists(f):
239 240 if f.endswith('data'):
240 241 # 'dstbase' may be empty (e.g. revlog format 0)
241 242 lockfile = os.path.join(dstbase, "lock")
242 243 # lock to avoid premature writing to the target
243 244 destlock = lock.lock(dstvfs, lockfile)
244 245 hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
245 246 hardlink)
246 247 num += n
247 248 if hardlink:
248 249 ui.debug("linked %d files\n" % num)
249 250 else:
250 251 ui.debug("copied %d files\n" % num)
251 252 return destlock
252 253 except: # re-raises
253 254 release(destlock)
254 255 raise
255 256
256 257 def clone(ui, peeropts, source, dest=None, pull=False, rev=None,
257 258 update=True, stream=False, branch=None):
258 259 """Make a copy of an existing repository.
259 260
260 261 Create a copy of an existing repository in a new directory. The
261 262 source and destination are URLs, as passed to the repository
262 263 function. Returns a pair of repository peers, the source and
263 264 newly created destination.
264 265
265 266 The location of the source is added to the new repository's
266 267 .hg/hgrc file, as the default to be used for future pulls and
267 268 pushes.
268 269
269 270 If an exception is raised, the partly cloned/updated destination
270 271 repository will be deleted.
271 272
272 273 Arguments:
273 274
274 275 source: repository object or URL
275 276
276 277 dest: URL of destination repository to create (defaults to base
277 278 name of source repository)
278 279
279 280 pull: always pull from source repository, even in local case
280 281
281 282 stream: stream raw data uncompressed from repository (fast over
282 283 LAN, slow over WAN)
283 284
284 285 rev: revision to clone up to (implies pull=True)
285 286
286 287 update: update working directory after clone completes, if
287 288 destination is local repository (True means update to default rev,
288 289 anything else is treated as a revision)
289 290
290 291 branch: branches to clone
291 292 """
292 293
293 294 if isinstance(source, str):
294 295 origsource = ui.expandpath(source)
295 296 source, branch = parseurl(origsource, branch)
296 297 srcpeer = peer(ui, peeropts, source)
297 298 else:
298 299 srcpeer = source.peer() # in case we were called with a localrepo
299 300 branch = (None, branch or [])
300 301 origsource = source = srcpeer.url()
301 302 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
302 303
303 304 if dest is None:
304 305 dest = defaultdest(source)
305 306 if dest:
306 307 ui.status(_("destination directory: %s\n") % dest)
307 308 else:
308 309 dest = ui.expandpath(dest)
309 310
310 311 dest = util.urllocalpath(dest)
311 312 source = util.urllocalpath(source)
312 313
313 314 if not dest:
314 315 raise util.Abort(_("empty destination path is not valid"))
315 316 if os.path.exists(dest):
316 317 if not os.path.isdir(dest):
317 318 raise util.Abort(_("destination '%s' already exists") % dest)
318 319 elif os.listdir(dest):
319 320 raise util.Abort(_("destination '%s' is not empty") % dest)
320 321
321 322 srclock = destlock = cleandir = None
322 323 srcrepo = srcpeer.local()
323 324 try:
324 325 abspath = origsource
325 326 if islocal(origsource):
326 327 abspath = os.path.abspath(util.urllocalpath(origsource))
327 328
328 329 if islocal(dest):
329 330 cleandir = dest
330 331
331 332 copy = False
332 333 if (srcrepo and srcrepo.cancopy() and islocal(dest)
333 334 and not phases.hassecret(srcrepo)):
334 335 copy = not pull and not rev
335 336
336 337 if copy:
337 338 try:
338 339 # we use a lock here because if we race with commit, we
339 340 # can end up with extra data in the cloned revlogs that's
340 341 # not pointed to by changesets, thus causing verify to
341 342 # fail
342 343 srclock = srcrepo.lock(wait=False)
343 344 except error.LockError:
344 345 copy = False
345 346
346 347 if copy:
347 348 srcrepo.hook('preoutgoing', throw=True, source='clone')
348 349 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
349 350 if not os.path.exists(dest):
350 351 os.mkdir(dest)
351 352 else:
352 353 # only clean up directories we create ourselves
353 354 cleandir = hgdir
354 355 try:
355 356 destpath = hgdir
356 357 util.makedir(destpath, notindexed=True)
357 358 except OSError, inst:
358 359 if inst.errno == errno.EEXIST:
359 360 cleandir = None
360 361 raise util.Abort(_("destination '%s' already exists")
361 362 % dest)
362 363 raise
363 364
364 365 destlock = copystore(ui, srcrepo, destpath)
365 366
366 367 # Recomputing branch cache might be slow on big repos,
367 368 # so just copy it
368 369 dstcachedir = os.path.join(destpath, 'cache')
369 370 srcbranchcache = srcrepo.sjoin('cache/branch2')
370 371 dstbranchcache = os.path.join(dstcachedir, 'branch2')
371 372 if os.path.exists(srcbranchcache):
372 373 if not os.path.exists(dstcachedir):
373 374 os.mkdir(dstcachedir)
374 375 util.copyfile(srcbranchcache, dstbranchcache)
375 376
376 377 # we need to re-init the repo after manually copying the data
377 378 # into it
378 379 destpeer = peer(srcrepo, peeropts, dest)
379 380 srcrepo.hook('outgoing', source='clone',
380 381 node=node.hex(node.nullid))
381 382 else:
382 383 try:
383 384 destpeer = peer(srcrepo or ui, peeropts, dest, create=True)
384 385 # only pass ui when no srcrepo
385 386 except OSError, inst:
386 387 if inst.errno == errno.EEXIST:
387 388 cleandir = None
388 389 raise util.Abort(_("destination '%s' already exists")
389 390 % dest)
390 391 raise
391 392
392 393 revs = None
393 394 if rev:
394 395 if not srcpeer.capable('lookup'):
395 396 raise util.Abort(_("src repository does not support "
396 397 "revision lookup and so doesn't "
397 398 "support clone by revision"))
398 399 revs = [srcpeer.lookup(r) for r in rev]
399 400 checkout = revs[0]
400 401 if destpeer.local():
401 402 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
402 403 elif srcrepo:
403 404 srcrepo.push(destpeer, revs=revs)
404 405 else:
405 406 raise util.Abort(_("clone from remote to remote not supported"))
406 407
407 408 cleandir = None
408 409
409 410 # clone all bookmarks except divergent ones
410 411 destrepo = destpeer.local()
411 412 if destrepo and srcpeer.capable("pushkey"):
412 413 rb = srcpeer.listkeys('bookmarks')
413 414 marks = destrepo._bookmarks
414 415 for k, n in rb.iteritems():
415 416 try:
416 417 m = destrepo.lookup(n)
417 418 marks[k] = m
418 419 except error.RepoLookupError:
419 420 pass
420 421 if rb:
421 422 marks.write()
422 423 elif srcrepo and destpeer.capable("pushkey"):
423 424 for k, n in srcrepo._bookmarks.iteritems():
424 425 destpeer.pushkey('bookmarks', k, '', hex(n))
425 426
426 427 if destrepo:
427 428 fp = destrepo.opener("hgrc", "w", text=True)
428 429 fp.write("[paths]\n")
429 430 u = util.url(abspath)
430 431 u.passwd = None
431 432 defaulturl = str(u)
432 433 fp.write("default = %s\n" % defaulturl)
433 434 fp.close()
434 435
435 436 destrepo.ui.setconfig('paths', 'default', defaulturl, 'clone')
436 437
437 438 if update:
438 439 if update is not True:
439 440 checkout = srcpeer.lookup(update)
440 441 uprev = None
441 442 status = None
442 443 if checkout is not None:
443 444 try:
444 445 uprev = destrepo.lookup(checkout)
445 446 except error.RepoLookupError:
446 447 pass
447 448 if uprev is None:
448 449 try:
449 450 uprev = destrepo._bookmarks['@']
450 451 update = '@'
451 452 bn = destrepo[uprev].branch()
452 453 if bn == 'default':
453 454 status = _("updating to bookmark @\n")
454 455 else:
455 456 status = (_("updating to bookmark @ on branch %s\n")
456 457 % bn)
457 458 except KeyError:
458 459 try:
459 460 uprev = destrepo.branchtip('default')
460 461 except error.RepoLookupError:
461 462 uprev = destrepo.lookup('tip')
462 463 if not status:
463 464 bn = destrepo[uprev].branch()
464 465 status = _("updating to branch %s\n") % bn
465 466 destrepo.ui.status(status)
466 467 _update(destrepo, uprev)
467 468 if update in destrepo._bookmarks:
468 469 bookmarks.setcurrent(destrepo, update)
469 470 finally:
470 471 release(srclock, destlock)
471 472 if cleandir is not None:
472 473 shutil.rmtree(cleandir, True)
473 474 if srcpeer is not None:
474 475 srcpeer.close()
475 476 return srcpeer, destpeer
476 477
477 478 def _showstats(repo, stats):
478 479 repo.ui.status(_("%d files updated, %d files merged, "
479 480 "%d files removed, %d files unresolved\n") % stats)
480 481
481 482 def updaterepo(repo, node, overwrite):
482 483 """Update the working directory to node.
483 484
484 485 When overwrite is set, changes are clobbered, merged else
485 486
486 487 returns stats (see pydoc mercurial.merge.applyupdates)"""
487 488 return mergemod.update(repo, node, False, overwrite, None,
488 489 labels=['working copy', 'destination'])
489 490
490 491 def update(repo, node):
491 492 """update the working directory to node, merging linear changes"""
492 493 stats = updaterepo(repo, node, False)
493 494 _showstats(repo, stats)
494 495 if stats[3]:
495 496 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
496 497 return stats[3] > 0
497 498
498 499 # naming conflict in clone()
499 500 _update = update
500 501
501 502 def clean(repo, node, show_stats=True):
502 503 """forcibly switch the working directory to node, clobbering changes"""
503 504 stats = updaterepo(repo, node, True)
504 505 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
505 506 if show_stats:
506 507 _showstats(repo, stats)
507 508 return stats[3] > 0
508 509
509 510 def merge(repo, node, force=None, remind=True):
510 511 """Branch merge with node, resolving changes. Return true if any
511 512 unresolved conflicts."""
512 513 stats = mergemod.update(repo, node, True, force, False)
513 514 _showstats(repo, stats)
514 515 if stats[3]:
515 516 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
516 517 "or 'hg update -C .' to abandon\n"))
517 518 elif remind:
518 519 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
519 520 return stats[3] > 0
520 521
521 522 def _incoming(displaychlist, subreporecurse, ui, repo, source,
522 523 opts, buffered=False):
523 524 """
524 525 Helper for incoming / gincoming.
525 526 displaychlist gets called with
526 527 (remoterepo, incomingchangesetlist, displayer) parameters,
527 528 and is supposed to contain only code that can't be unified.
528 529 """
529 530 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
530 531 other = peer(repo, opts, source)
531 532 ui.status(_('comparing with %s\n') % util.hidepassword(source))
532 533 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
533 534
534 535 if revs:
535 536 revs = [other.lookup(rev) for rev in revs]
536 537 other, chlist, cleanupfn = bundlerepo.getremotechanges(ui, repo, other,
537 538 revs, opts["bundle"], opts["force"])
538 539 try:
539 540 if not chlist:
540 541 ui.status(_("no changes found\n"))
541 542 return subreporecurse()
542 543
543 544 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
544 545 displaychlist(other, chlist, displayer)
545 546 displayer.close()
546 547 finally:
547 548 cleanupfn()
548 549 subreporecurse()
549 550 return 0 # exit code is zero since we found incoming changes
550 551
551 552 def incoming(ui, repo, source, opts):
552 553 def subreporecurse():
553 554 ret = 1
554 555 if opts.get('subrepos'):
555 556 ctx = repo[None]
556 557 for subpath in sorted(ctx.substate):
557 558 sub = ctx.sub(subpath)
558 559 ret = min(ret, sub.incoming(ui, source, opts))
559 560 return ret
560 561
561 562 def display(other, chlist, displayer):
562 563 limit = cmdutil.loglimit(opts)
563 564 if opts.get('newest_first'):
564 565 chlist.reverse()
565 566 count = 0
566 567 for n in chlist:
567 568 if limit is not None and count >= limit:
568 569 break
569 570 parents = [p for p in other.changelog.parents(n) if p != nullid]
570 571 if opts.get('no_merges') and len(parents) == 2:
571 572 continue
572 573 count += 1
573 574 displayer.show(other[n])
574 575 return _incoming(display, subreporecurse, ui, repo, source, opts)
575 576
576 577 def _outgoing(ui, repo, dest, opts):
577 578 dest = ui.expandpath(dest or 'default-push', dest or 'default')
578 579 dest, branches = parseurl(dest, opts.get('branch'))
579 580 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
580 581 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
581 582 if revs:
582 583 revs = [repo.lookup(rev) for rev in scmutil.revrange(repo, revs)]
583 584
584 585 other = peer(repo, opts, dest)
585 586 outgoing = discovery.findcommonoutgoing(repo.unfiltered(), other, revs,
586 587 force=opts.get('force'))
587 588 o = outgoing.missing
588 589 if not o:
589 590 scmutil.nochangesfound(repo.ui, repo, outgoing.excluded)
590 591 return o, other
591 592
592 593 def outgoing(ui, repo, dest, opts):
593 594 def recurse():
594 595 ret = 1
595 596 if opts.get('subrepos'):
596 597 ctx = repo[None]
597 598 for subpath in sorted(ctx.substate):
598 599 sub = ctx.sub(subpath)
599 600 ret = min(ret, sub.outgoing(ui, dest, opts))
600 601 return ret
601 602
602 603 limit = cmdutil.loglimit(opts)
603 604 o, other = _outgoing(ui, repo, dest, opts)
604 605 if not o:
605 606 cmdutil.outgoinghooks(ui, repo, other, opts, o)
606 607 return recurse()
607 608
608 609 if opts.get('newest_first'):
609 610 o.reverse()
610 611 displayer = cmdutil.show_changeset(ui, repo, opts)
611 612 count = 0
612 613 for n in o:
613 614 if limit is not None and count >= limit:
614 615 break
615 616 parents = [p for p in repo.changelog.parents(n) if p != nullid]
616 617 if opts.get('no_merges') and len(parents) == 2:
617 618 continue
618 619 count += 1
619 620 displayer.show(repo[n])
620 621 displayer.close()
621 622 cmdutil.outgoinghooks(ui, repo, other, opts, o)
622 623 recurse()
623 624 return 0 # exit code is zero since we found outgoing changes
624 625
625 626 def revert(repo, node, choose):
626 627 """revert changes to revision in node without updating dirstate"""
627 628 return mergemod.update(repo, node, False, True, choose)[3] > 0
628 629
629 630 def verify(repo):
630 631 """verify the consistency of a repository"""
631 632 return verifymod.verify(repo)
632 633
633 634 def remoteui(src, opts):
634 635 'build a remote ui from ui or repo and opts'
635 636 if util.safehasattr(src, 'baseui'): # looks like a repository
636 637 dst = src.baseui.copy() # drop repo-specific config
637 638 src = src.ui # copy target options from repo
638 639 else: # assume it's a global ui object
639 640 dst = src.copy() # keep all global options
640 641
641 642 # copy ssh-specific options
642 643 for o in 'ssh', 'remotecmd':
643 644 v = opts.get(o) or src.config('ui', o)
644 645 if v:
645 646 dst.setconfig("ui", o, v, 'copied')
646 647
647 648 # copy bundle-specific options
648 649 r = src.config('bundle', 'mainreporoot')
649 650 if r:
650 651 dst.setconfig('bundle', 'mainreporoot', r, 'copied')
651 652
652 653 # copy selected local settings to the remote ui
653 654 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
654 655 for key, val in src.configitems(sect):
655 656 dst.setconfig(sect, key, val, 'copied')
656 657 v = src.config('web', 'cacerts')
657 658 if v:
658 659 dst.setconfig('web', 'cacerts', util.expandpath(v), 'copied')
659 660
660 661 return dst
General Comments 0
You need to be logged in to leave comments. Login now