Mercurial > public > mercurial-scm > hg
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 |