Mercurial > hg
diff 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 |
line wrap: on
line diff
--- a/mercurial/localrepo.py Fri Sep 07 15:57:55 2018 -0700 +++ b/mercurial/localrepo.py Tue Sep 11 13:46:59 2018 -0700 @@ -426,7 +426,13 @@ 'bisect.state', } - def __init__(self, baseui, path, create=False, intents=None): + def __init__(self, baseui, path, intents=None): + """Create a new local repository instance. + + Most callers should use ``hg.repository()`` or ``localrepo.instance()`` + for obtaining a new repository object. + """ + self.requirements = set() self.filtername = None # wvfs: rooted at the repository root, used to access the working copy @@ -475,31 +481,12 @@ self.supported.add('exp-compression-%s' % name) if not self.vfs.isdir(): - if create: - self.requirements = newreporequirements(self.ui) - - if not self.wvfs.exists(): - self.wvfs.makedirs() - self.vfs.makedir(notindexed=True) - - if 'store' in self.requirements: - self.vfs.mkdir("store") - - # create an invalid changelog - self.vfs.append( - "00changelog.i", - '\0\0\0\2' # represents revlogv2 - ' dummy changelog to prevent using the old repo layout' - ) - else: - try: - self.vfs.stat() - except OSError as inst: - if inst.errno != errno.ENOENT: - raise - raise error.RepoError(_("repository %s not found") % path) - elif create: - raise error.RepoError(_("repository %s already exists") % path) + try: + self.vfs.stat() + except OSError as inst: + if inst.errno != errno.ENOENT: + raise + raise error.RepoError(_("repository %s not found") % path) else: try: self.requirements = scmutil.readrequires( @@ -546,8 +533,6 @@ else: # standard vfs self.svfs.audit = self._getsvfsward(self.svfs.audit) self._applyopenerreqs() - if create: - self._writerequirements() self._dirstatevalidatewarned = False @@ -2396,8 +2381,15 @@ return os.path.join(base, name.replace('journal', 'undo', 1)) def instance(ui, path, create, intents=None): - return localrepository(ui, util.urllocalpath(path), create, - intents=intents) + if create: + vfs = vfsmod.vfs(path, expandpath=True, realpath=True) + + if vfs.exists('.hg'): + raise error.RepoError(_('repository %s already exists') % path) + + createrepository(ui, vfs) + + return localrepository(ui, util.urllocalpath(path), intents=intents) def islocal(path): return True @@ -2447,3 +2439,34 @@ requirements.add('internal-phase') return requirements + +def createrepository(ui, wdirvfs): + """Create a new repository in a vfs. + + ``wdirvfs`` is a vfs instance pointing at the working directory. + ``requirements`` is a set of requirements for the new repository. + """ + requirements = newreporequirements(ui) + + if not wdirvfs.exists(): + wdirvfs.makedirs() + + hgvfs = vfsmod.vfs(wdirvfs.join(b'.hg')) + hgvfs.makedir(notindexed=True) + + if b'store' in requirements: + hgvfs.mkdir(b'store') + + # We create an invalid changelog outside the store so very old + # Mercurial versions (which didn't know about the requirements + # file) encounter an error on reading the changelog. This + # effectively locks out old clients and prevents them from + # mucking with a repo in an unknown format. + # + # The revlog header has version 2, which won't be recognized by + # such old clients. + hgvfs.append(b'00changelog.i', + b'\0\0\0\2 dummy changelog to prevent using the old repo ' + b'layout') + + scmutil.writerequires(hgvfs, requirements)