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