comparison mercurial/hg.py @ 17191:5884812686f7

peer: introduce peer methods to prepare for peer classes This introduces a peer method into all repository classes, which currently simply returns self. It also changes hg.repository so it now raises an exception if the supplied paths does not resolve to a localrepo or descendant. Finally, all call sites are changed to use the peer and local methods as appropriate, where peer is used whenever the code is dealing with a remote repository (even if it's on local disk).
author Sune Foldager <cryo@cyanite.org>
date Fri, 13 Jul 2012 21:46:53 +0200
parents 36a3016811d1
children 1ac628cd7113
comparison
equal deleted inserted replaced
17190:d99d0b559084 17191:5884812686f7
18 18
19 def _local(path): 19 def _local(path):
20 path = util.expandpath(util.urllocalpath(path)) 20 path = util.expandpath(util.urllocalpath(path))
21 return (os.path.isfile(path) and bundlerepo or localrepo) 21 return (os.path.isfile(path) and bundlerepo or localrepo)
22 22
23 def addbranchrevs(lrepo, repo, branches, revs): 23 def addbranchrevs(lrepo, other, branches, revs):
24 peer = other.peer() # a courtesy to callers using a localrepo for other
24 hashbranch, branches = branches 25 hashbranch, branches = branches
25 if not hashbranch and not branches: 26 if not hashbranch and not branches:
26 return revs or None, revs and revs[0] or None 27 return revs or None, revs and revs[0] or None
27 revs = revs and list(revs) or [] 28 revs = revs and list(revs) or []
28 if not repo.capable('branchmap'): 29 if not peer.capable('branchmap'):
29 if branches: 30 if branches:
30 raise util.Abort(_("remote branch lookup not supported")) 31 raise util.Abort(_("remote branch lookup not supported"))
31 revs.append(hashbranch) 32 revs.append(hashbranch)
32 return revs, revs[0] 33 return revs, revs[0]
33 branchmap = repo.branchmap() 34 branchmap = peer.branchmap()
34 35
35 def primary(branch): 36 def primary(branch):
36 if branch == '.': 37 if branch == '.':
37 if not lrepo or not lrepo.local(): 38 if not lrepo:
38 raise util.Abort(_("dirstate branch not accessible")) 39 raise util.Abort(_("dirstate branch not accessible"))
39 branch = lrepo.dirstate.branch() 40 branch = lrepo.dirstate.branch()
40 if branch in branchmap: 41 if branch in branchmap:
41 revs.extend(node.hex(r) for r in reversed(branchmap[branch])) 42 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
42 return True 43 return True
86 return _peerlookup(repo).islocal(repo) 87 return _peerlookup(repo).islocal(repo)
87 except AttributeError: 88 except AttributeError:
88 return False 89 return False
89 return repo.local() 90 return repo.local()
90 91
91 def repository(ui, path='', create=False): 92 def _peerorrepo(ui, path, create=False):
92 """return a repository object for the specified path""" 93 """return a repository object for the specified path"""
93 repo = _peerlookup(path).instance(ui, path, create) 94 obj = _peerlookup(path).instance(ui, path, create)
94 ui = getattr(repo, "ui", ui) 95 ui = getattr(obj, "ui", ui)
95 for name, module in extensions.extensions(): 96 for name, module in extensions.extensions():
96 hook = getattr(module, 'reposetup', None) 97 hook = getattr(module, 'reposetup', None)
97 if hook: 98 if hook:
98 hook(ui, repo) 99 hook(ui, obj)
100 return obj
101
102 def repository(ui, path='', create=False):
103 """return a repository object for the specified path"""
104 peer = _peerorrepo(ui, path, create)
105 repo = peer.local()
106 if not repo:
107 raise util.Abort(_("repository '%s' is not local") %
108 (path or peer.url()))
99 return repo 109 return repo
100 110
101 def peer(uiorrepo, opts, path, create=False): 111 def peer(uiorrepo, opts, path, create=False):
102 '''return a repository peer for the specified path''' 112 '''return a repository peer for the specified path'''
103 rui = remoteui(uiorrepo, opts) 113 rui = remoteui(uiorrepo, opts)
104 return repository(rui, path, create) 114 return _peerorrepo(rui, path, create).peer()
105 115
106 def defaultdest(source): 116 def defaultdest(source):
107 '''return default destination of clone if none is given''' 117 '''return default destination of clone if none is given'''
108 return os.path.basename(os.path.normpath(source)) 118 return os.path.basename(os.path.normpath(source))
109 119
122 origsource = ui.expandpath(source) 132 origsource = ui.expandpath(source)
123 source, branches = parseurl(origsource) 133 source, branches = parseurl(origsource)
124 srcrepo = repository(ui, source) 134 srcrepo = repository(ui, source)
125 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None) 135 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
126 else: 136 else:
127 srcrepo = source 137 srcrepo = source.local()
128 origsource = source = srcrepo.url() 138 origsource = source = srcrepo.url()
129 checkout = None 139 checkout = None
130 140
131 sharedpath = srcrepo.sharedpath # if our source is already sharing 141 sharedpath = srcrepo.sharedpath # if our source is already sharing
132 142
211 update=True, stream=False, branch=None): 221 update=True, stream=False, branch=None):
212 """Make a copy of an existing repository. 222 """Make a copy of an existing repository.
213 223
214 Create a copy of an existing repository in a new directory. The 224 Create a copy of an existing repository in a new directory. The
215 source and destination are URLs, as passed to the repository 225 source and destination are URLs, as passed to the repository
216 function. Returns a pair of repository objects, the source and 226 function. Returns a pair of repository peers, the source and
217 newly created destination. 227 newly created destination.
218 228
219 The location of the source is added to the new repository's 229 The location of the source is added to the new repository's
220 .hg/hgrc file, as the default to be used for future pulls and 230 .hg/hgrc file, as the default to be used for future pulls and
221 pushes. 231 pushes.
245 """ 255 """
246 256
247 if isinstance(source, str): 257 if isinstance(source, str):
248 origsource = ui.expandpath(source) 258 origsource = ui.expandpath(source)
249 source, branch = parseurl(origsource, branch) 259 source, branch = parseurl(origsource, branch)
250 srcrepo = repository(remoteui(ui, peeropts), source) 260 srcpeer = peer(ui, peeropts, source)
251 else: 261 else:
252 srcrepo = source 262 srcpeer = source.peer() # in case we were called with a localrepo
253 branch = (None, branch or []) 263 branch = (None, branch or [])
254 origsource = source = srcrepo.url() 264 origsource = source = srcpeer.url()
255 rev, checkout = addbranchrevs(srcrepo, srcrepo, branch, rev) 265 rev, checkout = addbranchrevs(srcpeer, srcpeer, branch, rev)
256 266
257 if dest is None: 267 if dest is None:
258 dest = defaultdest(source) 268 dest = defaultdest(source)
259 ui.status(_("destination directory: %s\n") % dest) 269 ui.status(_("destination directory: %s\n") % dest)
260 else: 270 else:
280 def cleanup(self): 290 def cleanup(self):
281 if self.dir_: 291 if self.dir_:
282 self.rmtree(self.dir_, True) 292 self.rmtree(self.dir_, True)
283 293
284 srclock = destlock = dircleanup = None 294 srclock = destlock = dircleanup = None
295 srcrepo = srcpeer.local()
285 try: 296 try:
286 abspath = origsource 297 abspath = origsource
287 if islocal(origsource): 298 if islocal(origsource):
288 abspath = os.path.abspath(util.urllocalpath(origsource)) 299 abspath = os.path.abspath(util.urllocalpath(origsource))
289 300
290 if islocal(dest): 301 if islocal(dest):
291 dircleanup = DirCleanup(dest) 302 dircleanup = DirCleanup(dest)
292 303
293 copy = False 304 copy = False
294 if srcrepo.cancopy() and islocal(dest) and not srcrepo.revs("secret()"): 305 if srcpeer.cancopy() and islocal(dest) and not srcrepo.revs("secret()"):
295 copy = not pull and not rev 306 copy = not pull and not rev
296 307
297 if copy: 308 if copy:
298 try: 309 try:
299 # we use a lock here because if we race with commit, we 310 # we use a lock here because if we race with commit, we
324 335
325 destlock = copystore(ui, srcrepo, destpath) 336 destlock = copystore(ui, srcrepo, destpath)
326 337
327 # we need to re-init the repo after manually copying the data 338 # we need to re-init the repo after manually copying the data
328 # into it 339 # into it
329 destrepo = repository(remoteui(ui, peeropts), dest) 340 destpeer = peer(ui, peeropts, dest)
330 srcrepo.hook('outgoing', source='clone', 341 srcrepo.hook('outgoing', source='clone',
331 node=node.hex(node.nullid)) 342 node=node.hex(node.nullid))
332 else: 343 else:
333 try: 344 try:
334 destrepo = repository(remoteui(ui, peeropts), dest, 345 destpeer = peer(ui, peeropts, dest, create=True)
335 create=True)
336 except OSError, inst: 346 except OSError, inst:
337 if inst.errno == errno.EEXIST: 347 if inst.errno == errno.EEXIST:
338 dircleanup.close() 348 dircleanup.close()
339 raise util.Abort(_("destination '%s' already exists") 349 raise util.Abort(_("destination '%s' already exists")
340 % dest) 350 % dest)
341 raise 351 raise
342 352
343 revs = None 353 revs = None
344 if rev: 354 if rev:
345 if not srcrepo.capable('lookup'): 355 if not srcpeer.capable('lookup'):
346 raise util.Abort(_("src repository does not support " 356 raise util.Abort(_("src repository does not support "
347 "revision lookup and so doesn't " 357 "revision lookup and so doesn't "
348 "support clone by revision")) 358 "support clone by revision"))
349 revs = [srcrepo.lookup(r) for r in rev] 359 revs = [srcpeer.lookup(r) for r in rev]
350 checkout = revs[0] 360 checkout = revs[0]
351 if destrepo.local(): 361 if destpeer.local():
352 destrepo.clone(srcrepo, heads=revs, stream=stream) 362 destpeer.local().clone(srcpeer, heads=revs, stream=stream)
353 elif srcrepo.local(): 363 elif srcrepo:
354 srcrepo.push(destrepo, revs=revs) 364 srcrepo.push(destpeer, revs=revs)
355 else: 365 else:
356 raise util.Abort(_("clone from remote to remote not supported")) 366 raise util.Abort(_("clone from remote to remote not supported"))
357 367
358 if dircleanup: 368 if dircleanup:
359 dircleanup.close() 369 dircleanup.close()
360 370
361 # clone all bookmarks except divergent ones 371 # clone all bookmarks except divergent ones
362 if destrepo.local() and srcrepo.capable("pushkey"): 372 destrepo = destpeer.local()
363 rb = srcrepo.listkeys('bookmarks') 373 if destrepo and srcpeer.capable("pushkey"):
374 rb = srcpeer.listkeys('bookmarks')
364 for k, n in rb.iteritems(): 375 for k, n in rb.iteritems():
365 try: 376 try:
366 m = destrepo.lookup(n) 377 m = destrepo.lookup(n)
367 destrepo._bookmarks[k] = m 378 destrepo._bookmarks[k] = m
368 except error.RepoLookupError: 379 except error.RepoLookupError:
369 pass 380 pass
370 if rb: 381 if rb:
371 bookmarks.write(destrepo) 382 bookmarks.write(destrepo)
372 elif srcrepo.local() and destrepo.capable("pushkey"): 383 elif srcrepo and destpeer.capable("pushkey"):
373 for k, n in srcrepo._bookmarks.iteritems(): 384 for k, n in srcrepo._bookmarks.iteritems():
374 destrepo.pushkey('bookmarks', k, '', hex(n)) 385 destpeer.pushkey('bookmarks', k, '', hex(n))
375 386
376 if destrepo.local(): 387 if destrepo:
377 fp = destrepo.opener("hgrc", "w", text=True) 388 fp = destrepo.opener("hgrc", "w", text=True)
378 fp.write("[paths]\n") 389 fp.write("[paths]\n")
379 u = util.url(abspath) 390 u = util.url(abspath)
380 u.passwd = None 391 u.passwd = None
381 defaulturl = str(u) 392 defaulturl = str(u)
384 395
385 destrepo.ui.setconfig('paths', 'default', defaulturl) 396 destrepo.ui.setconfig('paths', 'default', defaulturl)
386 397
387 if update: 398 if update:
388 if update is not True: 399 if update is not True:
389 checkout = update 400 checkout = srcrepo.lookup(update)
390 if srcrepo.local():
391 checkout = srcrepo.lookup(update)
392 for test in (checkout, 'default', 'tip'): 401 for test in (checkout, 'default', 'tip'):
393 if test is None: 402 if test is None:
394 continue 403 continue
395 try: 404 try:
396 uprev = destrepo.lookup(test) 405 uprev = destrepo.lookup(test)
399 continue 408 continue
400 bn = destrepo[uprev].branch() 409 bn = destrepo[uprev].branch()
401 destrepo.ui.status(_("updating to branch %s\n") % bn) 410 destrepo.ui.status(_("updating to branch %s\n") % bn)
402 _update(destrepo, uprev) 411 _update(destrepo, uprev)
403 412
404 return srcrepo, destrepo 413 return srcpeer, destpeer
405 finally: 414 finally:
406 release(srclock, destlock) 415 release(srclock, destlock)
407 if dircleanup is not None: 416 if dircleanup is not None:
408 dircleanup.cleanup() 417 dircleanup.cleanup()
409 if srcrepo is not None: 418 if srcpeer is not None:
410 srcrepo.close() 419 srcpeer.close()
411 420
412 def _showstats(repo, stats): 421 def _showstats(repo, stats):
413 repo.ui.status(_("%d files updated, %d files merged, " 422 repo.ui.status(_("%d files updated, %d files merged, "
414 "%d files removed, %d files unresolved\n") % stats) 423 "%d files removed, %d files unresolved\n") % stats)
415 424