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] |