mercurial/localrepo.py
changeset 39764 e4e881572382
parent 39763 5ccd791344f3
child 39765 3e801ffd7269
equal deleted inserted replaced
39763:5ccd791344f3 39764:e4e881572382
   378 
   378 
   379 def makelocalrepository(baseui, path, intents=None):
   379 def makelocalrepository(baseui, path, intents=None):
   380     """Create a local repository object.
   380     """Create a local repository object.
   381 
   381 
   382     Given arguments needed to construct a local repository, this function
   382     Given arguments needed to construct a local repository, this function
   383     derives a type suitable for representing that repository and returns an
   383     performs various early repository loading functionality (such as
   384     instance of it.
   384     reading the ``.hg/requires`` and ``.hg/hgrc`` files), validates that
       
   385     the repository can be opened, derives a type suitable for representing
       
   386     that repository, and returns an instance of it.
   385 
   387 
   386     The returned object conforms to the ``repository.completelocalrepository``
   388     The returned object conforms to the ``repository.completelocalrepository``
   387     interface.
   389     interface.
       
   390 
       
   391     The repository type is derived by calling a series of factory functions
       
   392     for each aspect/interface of the final repository. These are defined by
       
   393     ``REPO_INTERFACES``.
       
   394 
       
   395     Each factory function is called to produce a type implementing a specific
       
   396     interface. The cumulative list of returned types will be combined into a
       
   397     new type and that type will be instantiated to represent the local
       
   398     repository.
       
   399 
       
   400     The factory functions each receive various state that may be consulted
       
   401     as part of deriving a type.
       
   402 
       
   403     Extensions should wrap these factory functions to customize repository type
       
   404     creation. Note that an extension's wrapped function may be called even if
       
   405     that extension is not loaded for the repo being constructed. Extensions
       
   406     should check if their ``__name__`` appears in the
       
   407     ``extensionmodulenames`` set passed to the factory function and no-op if
       
   408     not.
   388     """
   409     """
   389     ui = baseui.copy()
   410     ui = baseui.copy()
   390     # Prevent copying repo configuration.
   411     # Prevent copying repo configuration.
   391     ui.copy = baseui.copy
   412     ui.copy = baseui.copy
   392 
   413 
   427         ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
   448         ui.readconfig(hgvfs.join(b'hgrc'), root=wdirvfs.base)
   428     except IOError:
   449     except IOError:
   429         pass
   450         pass
   430     else:
   451     else:
   431         extensions.loadall(ui)
   452         extensions.loadall(ui)
       
   453 
       
   454     # Set of module names of extensions loaded for this repository.
       
   455     extensionmodulenames = {m.__name__ for n, m in extensions.extensions(ui)}
   432 
   456 
   433     supportedrequirements = gathersupportedrequirements(ui)
   457     supportedrequirements = gathersupportedrequirements(ui)
   434 
   458 
   435     # We first validate the requirements are known.
   459     # We first validate the requirements are known.
   436     ensurerequirementsrecognized(requirements, supportedrequirements)
   460     ensurerequirementsrecognized(requirements, supportedrequirements)
   488 
   512 
   489     # The cache vfs is used to manage cache files.
   513     # The cache vfs is used to manage cache files.
   490     cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
   514     cachevfs = vfsmod.vfs(cachepath, cacheaudited=True)
   491     cachevfs.createmode = store.createmode
   515     cachevfs.createmode = store.createmode
   492 
   516 
   493     return localrepository(
   517     # Now resolve the type for the repository object. We do this by repeatedly
       
   518     # calling a factory function to produces types for specific aspects of the
       
   519     # repo's operation. The aggregate returned types are used as base classes
       
   520     # for a dynamically-derived type, which will represent our new repository.
       
   521 
       
   522     bases = []
       
   523     extrastate = {}
       
   524 
       
   525     for iface, fn in REPO_INTERFACES:
       
   526         # We pass all potentially useful state to give extensions tons of
       
   527         # flexibility.
       
   528         typ = fn(ui=ui,
       
   529                  intents=intents,
       
   530                  requirements=requirements,
       
   531                  wdirvfs=wdirvfs,
       
   532                  hgvfs=hgvfs,
       
   533                  store=store,
       
   534                  storevfs=storevfs,
       
   535                  storeoptions=storevfs.options,
       
   536                  cachevfs=cachevfs,
       
   537                  extensionmodulenames=extensionmodulenames,
       
   538                  extrastate=extrastate,
       
   539                  baseclasses=bases)
       
   540 
       
   541         if not isinstance(typ, type):
       
   542             raise error.ProgrammingError('unable to construct type for %s' %
       
   543                                          iface)
       
   544 
       
   545         bases.append(typ)
       
   546 
       
   547     # type() allows you to use characters in type names that wouldn't be
       
   548     # recognized as Python symbols in source code. We abuse that to add
       
   549     # rich information about our constructed repo.
       
   550     name = pycompat.sysstr(b'derivedrepo:%s<%s>' % (
       
   551         wdirvfs.base,
       
   552         b','.join(sorted(requirements))))
       
   553 
       
   554     cls = type(name, tuple(bases), {})
       
   555 
       
   556     return cls(
   494         baseui=baseui,
   557         baseui=baseui,
   495         ui=ui,
   558         ui=ui,
   496         origroot=path,
   559         origroot=path,
   497         wdirvfs=wdirvfs,
   560         wdirvfs=wdirvfs,
   498         hgvfs=hgvfs,
   561         hgvfs=hgvfs,
   664         if r.startswith(b'exp-compression-'):
   727         if r.startswith(b'exp-compression-'):
   665             options[b'compengine'] = r[len(b'exp-compression-'):]
   728             options[b'compengine'] = r[len(b'exp-compression-'):]
   666 
   729 
   667     return options
   730     return options
   668 
   731 
   669 @interfaceutil.implementer(repository.completelocalrepository)
   732 def makemain(**kwargs):
       
   733     """Produce a type conforming to ``ilocalrepositorymain``."""
       
   734     return localrepository
       
   735 
       
   736 @interfaceutil.implementer(repository.ilocalrepositoryfilestorage)
       
   737 class revlogfilestorage(object):
       
   738     """File storage when using revlogs."""
       
   739 
       
   740     def file(self, path):
       
   741         if path[0] == b'/':
       
   742             path = path[1:]
       
   743 
       
   744         return filelog.filelog(self.svfs, path)
       
   745 
       
   746 def makefilestorage(requirements, **kwargs):
       
   747     """Produce a type conforming to ``ilocalrepositoryfilestorage``."""
       
   748     return revlogfilestorage
       
   749 
       
   750 # List of repository interfaces and factory functions for them. Each
       
   751 # will be called in order during ``makelocalrepository()`` to iteratively
       
   752 # derive the final type for a local repository instance.
       
   753 REPO_INTERFACES = [
       
   754     (repository.ilocalrepositorymain, makemain),
       
   755     (repository.ilocalrepositoryfilestorage, makefilestorage),
       
   756 ]
       
   757 
       
   758 @interfaceutil.implementer(repository.ilocalrepositorymain)
   670 class localrepository(object):
   759 class localrepository(object):
       
   760     """Main class for representing local repositories.
       
   761 
       
   762     All local repositories are instances of this class.
       
   763 
       
   764     Constructed on its own, instances of this class are not usable as
       
   765     repository objects. To obtain a usable repository object, call
       
   766     ``hg.repository()``, ``localrepo.instance()``, or
       
   767     ``localrepo.makelocalrepository()``. The latter is the lowest-level.
       
   768     ``instance()`` adds support for creating new repositories.
       
   769     ``hg.repository()`` adds more extension integration, including calling
       
   770     ``reposetup()``. Generally speaking, ``hg.repository()`` should be
       
   771     used.
       
   772     """
   671 
   773 
   672     # obsolete experimental requirements:
   774     # obsolete experimental requirements:
   673     #  - manifestv2: An experimental new manifest format that allowed
   775     #  - manifestv2: An experimental new manifest format that allowed
   674     #    for stem compression of long paths. Experiment ended up not
   776     #    for stem compression of long paths. Experiment ended up not
   675     #    being successful (repository sizes went up due to worse delta
   777     #    being successful (repository sizes went up due to worse delta
  1322             return 'store'
  1424             return 'store'
  1323         return None
  1425         return None
  1324 
  1426 
  1325     def wjoin(self, f, *insidef):
  1427     def wjoin(self, f, *insidef):
  1326         return self.vfs.reljoin(self.root, f, *insidef)
  1428         return self.vfs.reljoin(self.root, f, *insidef)
  1327 
       
  1328     def file(self, f):
       
  1329         if f[0] == '/':
       
  1330             f = f[1:]
       
  1331         return filelog.filelog(self.svfs, f)
       
  1332 
  1429 
  1333     def setparents(self, p1, p2=nullid):
  1430     def setparents(self, p1, p2=nullid):
  1334         with self.dirstate.parentchange():
  1431         with self.dirstate.parentchange():
  1335             copies = self.dirstate.setparents(p1, p2)
  1432             copies = self.dirstate.setparents(p1, p2)
  1336             pctx = self[p1]
  1433             pctx = self[p1]