mercurial/localrepo.py
changeset 39693 5b8e9b2060ef
parent 39692 6a3162ed881d
child 39695 cb2dcfa5cade
equal deleted inserted replaced
39692:6a3162ed881d 39693:5b8e9b2060ef
   428     except IOError:
   428     except IOError:
   429         pass
   429         pass
   430     else:
   430     else:
   431         extensions.loadall(ui)
   431         extensions.loadall(ui)
   432 
   432 
       
   433     supportedrequirements = gathersupportedrequirements(ui)
       
   434     ensurerequirementsrecognized(requirements, supportedrequirements)
       
   435 
       
   436     # At this point, we know we should be capable of opening the repository.
       
   437     # Now get on with doing that.
       
   438 
   433     return localrepository(
   439     return localrepository(
   434         baseui=baseui,
   440         baseui=baseui,
   435         ui=ui,
   441         ui=ui,
   436         origroot=path,
   442         origroot=path,
   437         wdirvfs=wdirvfs,
   443         wdirvfs=wdirvfs,
   438         hgvfs=hgvfs,
   444         hgvfs=hgvfs,
   439         requirements=requirements,
   445         requirements=requirements,
       
   446         supportedrequirements=supportedrequirements,
   440         intents=intents)
   447         intents=intents)
       
   448 
       
   449 def gathersupportedrequirements(ui):
       
   450     """Determine the complete set of recognized requirements."""
       
   451     # Start with all requirements supported by this file.
       
   452     supported = set(localrepository._basesupported)
       
   453 
       
   454     # Execute ``featuresetupfuncs`` entries if they belong to an extension
       
   455     # relevant to this ui instance.
       
   456     modules = {m.__name__ for n, m in extensions.extensions(ui)}
       
   457 
       
   458     for fn in featuresetupfuncs:
       
   459         if fn.__module__ in modules:
       
   460             fn(ui, supported)
       
   461 
       
   462     # Add derived requirements from registered compression engines.
       
   463     for name in util.compengines:
       
   464         engine = util.compengines[name]
       
   465         if engine.revlogheader():
       
   466             supported.add(b'exp-compression-%s' % name)
       
   467 
       
   468     return supported
       
   469 
       
   470 def ensurerequirementsrecognized(requirements, supported):
       
   471     """Validate that a set of local requirements is recognized.
       
   472 
       
   473     Receives a set of requirements. Raises an ``error.RepoError`` if there
       
   474     exists any requirement in that set that currently loaded code doesn't
       
   475     recognize.
       
   476 
       
   477     Returns a set of supported requirements.
       
   478     """
       
   479     missing = set()
       
   480 
       
   481     for requirement in requirements:
       
   482         if requirement in supported:
       
   483             continue
       
   484 
       
   485         if not requirement or not requirement[0:1].isalnum():
       
   486             raise error.RequirementError(_(b'.hg/requires file is corrupt'))
       
   487 
       
   488         missing.add(requirement)
       
   489 
       
   490     if missing:
       
   491         raise error.RequirementError(
       
   492             _(b'repository requires features unknown to this Mercurial: %s') %
       
   493             b' '.join(sorted(missing)),
       
   494             hint=_(b'see https://mercurial-scm.org/wiki/MissingRequirement '
       
   495                    b'for more information'))
   441 
   496 
   442 @interfaceutil.implementer(repository.completelocalrepository)
   497 @interfaceutil.implementer(repository.completelocalrepository)
   443 class localrepository(object):
   498 class localrepository(object):
   444 
   499 
   445     # obsolete experimental requirements:
   500     # obsolete experimental requirements:
   488         # the remainig bit and drop this line
   543         # the remainig bit and drop this line
   489         'bisect.state',
   544         'bisect.state',
   490     }
   545     }
   491 
   546 
   492     def __init__(self, baseui, ui, origroot, wdirvfs, hgvfs, requirements,
   547     def __init__(self, baseui, ui, origroot, wdirvfs, hgvfs, requirements,
   493                  intents=None):
   548                  supportedrequirements, intents=None):
   494         """Create a new local repository instance.
   549         """Create a new local repository instance.
   495 
   550 
   496         Most callers should use ``hg.repository()``, ``localrepo.instance()``,
   551         Most callers should use ``hg.repository()``, ``localrepo.instance()``,
   497         or ``localrepo.makelocalrepository()`` for obtaining a new repository
   552         or ``localrepo.makelocalrepository()`` for obtaining a new repository
   498         object.
   553         object.
   514         hgvfs
   569         hgvfs
   515            ``vfs.vfs`` rooted at .hg/
   570            ``vfs.vfs`` rooted at .hg/
   516 
   571 
   517         requirements
   572         requirements
   518            ``set`` of bytestrings representing repository opening requirements.
   573            ``set`` of bytestrings representing repository opening requirements.
       
   574 
       
   575         supportedrequirements
       
   576            ``set`` of bytestrings representing repository requirements that we
       
   577            know how to open. May be a supetset of ``requirements``.
   519 
   578 
   520         intents
   579         intents
   521            ``set`` of system strings indicating what this repo will be used
   580            ``set`` of system strings indicating what this repo will be used
   522            for.
   581            for.
   523         """
   582         """
   528         self.wvfs = wdirvfs
   587         self.wvfs = wdirvfs
   529         self.root = wdirvfs.base
   588         self.root = wdirvfs.base
   530         # vfs rooted at .hg/. Used to access most non-store paths.
   589         # vfs rooted at .hg/. Used to access most non-store paths.
   531         self.vfs = hgvfs
   590         self.vfs = hgvfs
   532         self.path = hgvfs.base
   591         self.path = hgvfs.base
       
   592         self.requirements = requirements
       
   593         self.supported = supportedrequirements
   533 
   594 
   534         self.filtername = None
   595         self.filtername = None
   535         # svfs: usually rooted at .hg/store, used to access repository history
   596         # svfs: usually rooted at .hg/store, used to access repository history
   536         # If this is a shared repository, this vfs may point to another
   597         # If this is a shared repository, this vfs may point to another
   537         # repository's .hg/store directory.
   598         # repository's .hg/store directory.
   543         # A list of callback to shape the phase if no data were found.
   604         # A list of callback to shape the phase if no data were found.
   544         # Callback are in the form: func(repo, roots) --> processed root.
   605         # Callback are in the form: func(repo, roots) --> processed root.
   545         # This list it to be filled by extension during repo setup
   606         # This list it to be filled by extension during repo setup
   546         self._phasedefaults = []
   607         self._phasedefaults = []
   547 
   608 
   548         if featuresetupfuncs:
       
   549             self.supported = set(self._basesupported) # use private copy
       
   550             extmods = set(m.__name__ for n, m
       
   551                           in extensions.extensions(self.ui))
       
   552             for setupfunc in featuresetupfuncs:
       
   553                 if setupfunc.__module__ in extmods:
       
   554                     setupfunc(self.ui, self.supported)
       
   555         else:
       
   556             self.supported = self._basesupported
       
   557         color.setup(self.ui)
   609         color.setup(self.ui)
   558 
       
   559         # Add compression engines.
       
   560         for name in util.compengines:
       
   561             engine = util.compengines[name]
       
   562             if engine.revlogheader():
       
   563                 self.supported.add('exp-compression-%s' % name)
       
   564 
       
   565         # Validate that all seen repository requirements are supported.
       
   566         missingrequirements = []
       
   567         for r in requirements:
       
   568             if r not in self.supported:
       
   569                 if not r or not r[0:1].isalnum():
       
   570                     raise error.RequirementError(
       
   571                         _(".hg/requires file is corrupt"))
       
   572                 missingrequirements.append(r)
       
   573         missingrequirements.sort()
       
   574         if missingrequirements:
       
   575             raise error.RequirementError(
       
   576                 _("repository requires features unknown to this Mercurial: %s")
       
   577                 % " ".join(missingrequirements),
       
   578                 hint=_("see https://mercurial-scm.org/wiki/MissingRequirement"
       
   579                        " for more information"))
       
   580 
       
   581         self.requirements = requirements
       
   582 
   610 
   583         cachepath = self.vfs.join('cache')
   611         cachepath = self.vfs.join('cache')
   584         self.sharedpath = self.path
   612         self.sharedpath = self.path
   585         try:
   613         try:
   586             sharedpath = self.vfs.read("sharedpath").rstrip('\n')
   614             sharedpath = self.vfs.read("sharedpath").rstrip('\n')