localrepo: validate supported requirements in makelocalrepository()
This should be a glorified code move. I did take the opportunity to
refactor things. We now have a separate function for gathering
requirements and one for validating them.
I also mode cosmetic changes to the code, such as not using
abbreviations and using a set instead of list to model missing
requirements.
Differential Revision: https://phab.mercurial-scm.org/D4569
--- a/mercurial/localrepo.py Wed Sep 12 14:45:52 2018 -0700
+++ b/mercurial/localrepo.py Wed Sep 12 14:54:17 2018 -0700
@@ -430,6 +430,12 @@
else:
extensions.loadall(ui)
+ supportedrequirements = gathersupportedrequirements(ui)
+ ensurerequirementsrecognized(requirements, supportedrequirements)
+
+ # At this point, we know we should be capable of opening the repository.
+ # Now get on with doing that.
+
return localrepository(
baseui=baseui,
ui=ui,
@@ -437,8 +443,57 @@
wdirvfs=wdirvfs,
hgvfs=hgvfs,
requirements=requirements,
+ supportedrequirements=supportedrequirements,
intents=intents)
+def gathersupportedrequirements(ui):
+ """Determine the complete set of recognized requirements."""
+ # Start with all requirements supported by this file.
+ supported = set(localrepository._basesupported)
+
+ # Execute ``featuresetupfuncs`` entries if they belong to an extension
+ # relevant to this ui instance.
+ modules = {m.__name__ for n, m in extensions.extensions(ui)}
+
+ for fn in featuresetupfuncs:
+ if fn.__module__ in modules:
+ fn(ui, supported)
+
+ # Add derived requirements from registered compression engines.
+ for name in util.compengines:
+ engine = util.compengines[name]
+ if engine.revlogheader():
+ supported.add(b'exp-compression-%s' % name)
+
+ return supported
+
+def ensurerequirementsrecognized(requirements, supported):
+ """Validate that a set of local requirements is recognized.
+
+ Receives a set of requirements. Raises an ``error.RepoError`` if there
+ exists any requirement in that set that currently loaded code doesn't
+ recognize.
+
+ Returns a set of supported requirements.
+ """
+ missing = set()
+
+ for requirement in requirements:
+ if requirement in supported:
+ continue
+
+ if not requirement or not requirement[0:1].isalnum():
+ raise error.RequirementError(_(b'.hg/requires file is corrupt'))
+
+ missing.add(requirement)
+
+ if missing:
+ raise error.RequirementError(
+ _(b'repository requires features unknown to this Mercurial: %s') %
+ b' '.join(sorted(missing)),
+ hint=_(b'see https://mercurial-scm.org/wiki/MissingRequirement '
+ b'for more information'))
+
@interfaceutil.implementer(repository.completelocalrepository)
class localrepository(object):
@@ -490,7 +545,7 @@
}
def __init__(self, baseui, ui, origroot, wdirvfs, hgvfs, requirements,
- intents=None):
+ supportedrequirements, intents=None):
"""Create a new local repository instance.
Most callers should use ``hg.repository()``, ``localrepo.instance()``,
@@ -517,6 +572,10 @@
requirements
``set`` of bytestrings representing repository opening requirements.
+ supportedrequirements
+ ``set`` of bytestrings representing repository requirements that we
+ know how to open. May be a supetset of ``requirements``.
+
intents
``set`` of system strings indicating what this repo will be used
for.
@@ -530,6 +589,8 @@
# vfs rooted at .hg/. Used to access most non-store paths.
self.vfs = hgvfs
self.path = hgvfs.base
+ self.requirements = requirements
+ self.supported = supportedrequirements
self.filtername = None
# svfs: usually rooted at .hg/store, used to access repository history
@@ -545,41 +606,8 @@
# This list it to be filled by extension during repo setup
self._phasedefaults = []
- if featuresetupfuncs:
- self.supported = set(self._basesupported) # use private copy
- extmods = set(m.__name__ for n, m
- in extensions.extensions(self.ui))
- for setupfunc in featuresetupfuncs:
- if setupfunc.__module__ in extmods:
- setupfunc(self.ui, self.supported)
- else:
- self.supported = self._basesupported
color.setup(self.ui)
- # Add compression engines.
- for name in util.compengines:
- engine = util.compengines[name]
- if engine.revlogheader():
- self.supported.add('exp-compression-%s' % name)
-
- # Validate that all seen repository requirements are supported.
- missingrequirements = []
- for r in requirements:
- if r not in self.supported:
- if not r or not r[0:1].isalnum():
- raise error.RequirementError(
- _(".hg/requires file is corrupt"))
- missingrequirements.append(r)
- missingrequirements.sort()
- if missingrequirements:
- raise error.RequirementError(
- _("repository requires features unknown to this Mercurial: %s")
- % " ".join(missingrequirements),
- hint=_("see https://mercurial-scm.org/wiki/MissingRequirement"
- " for more information"))
-
- self.requirements = requirements
-
cachepath = self.vfs.join('cache')
self.sharedpath = self.path
try: