D4534: localrepo: move repo creation logic out of localrepository.__init__
This revision was automatically updated to reflect the committed changes. Closed by commit rHG7ce9dea3a14a: localrepo: move repo creation logic out of localrepository.__init__ (API) (authored by indygreg, committed by ). REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D4534?vs=10911=10924 REVISION DETAIL https://phab.mercurial-scm.org/D4534 AFFECTED FILES hgext/keyword.py mercurial/localrepo.py tests/test-status-inprocess.py CHANGE DETAILS diff --git a/tests/test-status-inprocess.py b/tests/test-status-inprocess.py --- a/tests/test-status-inprocess.py +++ b/tests/test-status-inprocess.py @@ -22,7 +22,7 @@ u = uimod.ui.load() print('% creating repo') -repo = localrepo.localrepository(u, b'.', create=True) +repo = localrepo.instance(u, b'.', create=True) f = open('test.py', 'w') try: diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -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') + +
D4534: localrepo: move repo creation logic out of localrepository.__init__
indygreg created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY 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()``. REPOSITORY rHG Mercurial REVISION DETAIL https://phab.mercurial-scm.org/D4534 AFFECTED FILES hgext/keyword.py mercurial/localrepo.py tests/test-status-inprocess.py CHANGE DETAILS diff --git a/tests/test-status-inprocess.py b/tests/test-status-inprocess.py --- a/tests/test-status-inprocess.py +++ b/tests/test-status-inprocess.py @@ -22,7 +22,7 @@ u = uimod.ui.load() print('% creating repo') -repo = localrepo.localrepository(u, b'.', create=True) +repo = localrepo.instance(u, b'.', create=True) f = open('test.py', 'w') try: diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -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')