Mercurial > hg
comparison mercurial/localrepo.py @ 39548:7ce9dea3a14a
localrepo: move repo creation logic out of localrepository.__init__ (API)
It has long bothered me that local repository creation is handled as
part of localrepository.__init__. Upcoming changes I want to make
around how repositories are initialized and instantiated will make
the continued existence of repository creation code in
localrepository.__init__ even more awkward.
localrepository instances are almost never constructed directly:
instead, callers are supposed to go through hg.repository() to obtain
a handle on a repository. And hg.repository() calls
localrepo.instance() to return a new repo instance.
This commit teaches localrepo.instance() to handle the create=True
logic. Most of the code for repo construction has been moved to a
standalone function. This allows extensions to monkeypatch the function
to further customize freshly-created repositories.
A few calls to localrepo.localrepository.__init__ that were passing
create=True were converted to call localrepo.instance().
.. api:: local repo creation moved out of constructor
``localrepo.localrepository.__init__`` no longer accepts a
``create`` argument to create a new repository. New repository
creation is now performed as part of ``localrepo.instance()``
and the bulk of the work is performed by
``localrepo.createrepository()``.
Differential Revision: https://phab.mercurial-scm.org/D4534
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Tue, 11 Sep 2018 13:46:59 -0700 |
parents | 41aa5dced975 |
children | 089fc0db0954 |
comparison
equal
deleted
inserted
replaced
39546:41aa5dced975 | 39548:7ce9dea3a14a |
---|---|
424 # this changeset was introduced. Someone should fix | 424 # this changeset was introduced. Someone should fix |
425 # the remainig bit and drop this line | 425 # the remainig bit and drop this line |
426 'bisect.state', | 426 'bisect.state', |
427 } | 427 } |
428 | 428 |
429 def __init__(self, baseui, path, create=False, intents=None): | 429 def __init__(self, baseui, path, intents=None): |
430 """Create a new local repository instance. | |
431 | |
432 Most callers should use ``hg.repository()`` or ``localrepo.instance()`` | |
433 for obtaining a new repository object. | |
434 """ | |
435 | |
430 self.requirements = set() | 436 self.requirements = set() |
431 self.filtername = None | 437 self.filtername = None |
432 # wvfs: rooted at the repository root, used to access the working copy | 438 # wvfs: rooted at the repository root, used to access the working copy |
433 self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True) | 439 self.wvfs = vfsmod.vfs(path, expandpath=True, realpath=True) |
434 # vfs: rooted at .hg, used to access repo files outside of .hg/store | 440 # vfs: rooted at .hg, used to access repo files outside of .hg/store |
473 engine = util.compengines[name] | 479 engine = util.compengines[name] |
474 if engine.revlogheader(): | 480 if engine.revlogheader(): |
475 self.supported.add('exp-compression-%s' % name) | 481 self.supported.add('exp-compression-%s' % name) |
476 | 482 |
477 if not self.vfs.isdir(): | 483 if not self.vfs.isdir(): |
478 if create: | 484 try: |
479 self.requirements = newreporequirements(self.ui) | 485 self.vfs.stat() |
480 | 486 except OSError as inst: |
481 if not self.wvfs.exists(): | 487 if inst.errno != errno.ENOENT: |
482 self.wvfs.makedirs() | 488 raise |
483 self.vfs.makedir(notindexed=True) | 489 raise error.RepoError(_("repository %s not found") % path) |
484 | |
485 if 'store' in self.requirements: | |
486 self.vfs.mkdir("store") | |
487 | |
488 # create an invalid changelog | |
489 self.vfs.append( | |
490 "00changelog.i", | |
491 '\0\0\0\2' # represents revlogv2 | |
492 ' dummy changelog to prevent using the old repo layout' | |
493 ) | |
494 else: | |
495 try: | |
496 self.vfs.stat() | |
497 except OSError as inst: | |
498 if inst.errno != errno.ENOENT: | |
499 raise | |
500 raise error.RepoError(_("repository %s not found") % path) | |
501 elif create: | |
502 raise error.RepoError(_("repository %s already exists") % path) | |
503 else: | 490 else: |
504 try: | 491 try: |
505 self.requirements = scmutil.readrequires( | 492 self.requirements = scmutil.readrequires( |
506 self.vfs, self.supported) | 493 self.vfs, self.supported) |
507 except IOError as inst: | 494 except IOError as inst: |
544 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs | 531 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs |
545 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit) | 532 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit) |
546 else: # standard vfs | 533 else: # standard vfs |
547 self.svfs.audit = self._getsvfsward(self.svfs.audit) | 534 self.svfs.audit = self._getsvfsward(self.svfs.audit) |
548 self._applyopenerreqs() | 535 self._applyopenerreqs() |
549 if create: | |
550 self._writerequirements() | |
551 | 536 |
552 self._dirstatevalidatewarned = False | 537 self._dirstatevalidatewarned = False |
553 | 538 |
554 self._branchcaches = {} | 539 self._branchcaches = {} |
555 self._revbranchcache = None | 540 self._revbranchcache = None |
2394 base, name = os.path.split(fn) | 2379 base, name = os.path.split(fn) |
2395 assert name.startswith('journal') | 2380 assert name.startswith('journal') |
2396 return os.path.join(base, name.replace('journal', 'undo', 1)) | 2381 return os.path.join(base, name.replace('journal', 'undo', 1)) |
2397 | 2382 |
2398 def instance(ui, path, create, intents=None): | 2383 def instance(ui, path, create, intents=None): |
2399 return localrepository(ui, util.urllocalpath(path), create, | 2384 if create: |
2400 intents=intents) | 2385 vfs = vfsmod.vfs(path, expandpath=True, realpath=True) |
2386 | |
2387 if vfs.exists('.hg'): | |
2388 raise error.RepoError(_('repository %s already exists') % path) | |
2389 | |
2390 createrepository(ui, vfs) | |
2391 | |
2392 return localrepository(ui, util.urllocalpath(path), intents=intents) | |
2401 | 2393 |
2402 def islocal(path): | 2394 def islocal(path): |
2403 return True | 2395 return True |
2404 | 2396 |
2405 def newreporequirements(ui): | 2397 def newreporequirements(ui): |
2445 # experimental config: format.internal-phase | 2437 # experimental config: format.internal-phase |
2446 if ui.configbool('format', 'internal-phase'): | 2438 if ui.configbool('format', 'internal-phase'): |
2447 requirements.add('internal-phase') | 2439 requirements.add('internal-phase') |
2448 | 2440 |
2449 return requirements | 2441 return requirements |
2442 | |
2443 def createrepository(ui, wdirvfs): | |
2444 """Create a new repository in a vfs. | |
2445 | |
2446 ``wdirvfs`` is a vfs instance pointing at the working directory. | |
2447 ``requirements`` is a set of requirements for the new repository. | |
2448 """ | |
2449 requirements = newreporequirements(ui) | |
2450 | |
2451 if not wdirvfs.exists(): | |
2452 wdirvfs.makedirs() | |
2453 | |
2454 hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) | |
2455 hgvfs.makedir(notindexed=True) | |
2456 | |
2457 if b'store' in requirements: | |
2458 hgvfs.mkdir(b'store') | |
2459 | |
2460 # We create an invalid changelog outside the store so very old | |
2461 # Mercurial versions (which didn't know about the requirements | |
2462 # file) encounter an error on reading the changelog. This | |
2463 # effectively locks out old clients and prevents them from | |
2464 # mucking with a repo in an unknown format. | |
2465 # | |
2466 # The revlog header has version 2, which won't be recognized by | |
2467 # such old clients. | |
2468 hgvfs.append(b'00changelog.i', | |
2469 b'\0\0\0\2 dummy changelog to prevent using the old repo ' | |
2470 b'layout') | |
2471 | |
2472 scmutil.writerequires(hgvfs, requirements) |