479 # The store has changed over time and the exact layout is dictated by |
479 # The store has changed over time and the exact layout is dictated by |
480 # requirements. The store interface abstracts differences across all |
480 # requirements. The store interface abstracts differences across all |
481 # of them. |
481 # of them. |
482 store = makestore(requirements, storebasepath, |
482 store = makestore(requirements, storebasepath, |
483 lambda base: vfsmod.vfs(base, cacheaudited=True)) |
483 lambda base: vfsmod.vfs(base, cacheaudited=True)) |
484 |
|
485 hgvfs.createmode = store.createmode |
484 hgvfs.createmode = store.createmode |
|
485 |
|
486 storevfs = store.vfs |
|
487 storevfs.options = resolvestorevfsoptions(ui, requirements) |
486 |
488 |
487 # The cache vfs is used to manage cache files. |
489 # The cache vfs is used to manage cache files. |
488 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True) |
490 cachevfs = vfsmod.vfs(cachepath, cacheaudited=True) |
489 cachevfs.createmode = store.createmode |
491 cachevfs.createmode = store.createmode |
490 |
492 |
575 b'dotencode' in requirements) |
577 b'dotencode' in requirements) |
576 |
578 |
577 return storemod.encodedstore(path, vfstype) |
579 return storemod.encodedstore(path, vfstype) |
578 |
580 |
579 return storemod.basicstore(path, vfstype) |
581 return storemod.basicstore(path, vfstype) |
|
582 |
|
583 def resolvestorevfsoptions(ui, requirements): |
|
584 """Resolve the options to pass to the store vfs opener. |
|
585 |
|
586 The returned dict is used to influence behavior of the storage layer. |
|
587 """ |
|
588 options = {} |
|
589 |
|
590 if b'treemanifest' in requirements: |
|
591 options[b'treemanifest'] = True |
|
592 |
|
593 # experimental config: format.manifestcachesize |
|
594 manifestcachesize = ui.configint(b'format', b'manifestcachesize') |
|
595 if manifestcachesize is not None: |
|
596 options[b'manifestcachesize'] = manifestcachesize |
|
597 |
|
598 # In the absence of another requirement superseding a revlog-related |
|
599 # requirement, we have to assume the repo is using revlog version 0. |
|
600 # This revlog format is super old and we don't bother trying to parse |
|
601 # opener options for it because those options wouldn't do anything |
|
602 # meaningful on such old repos. |
|
603 if b'revlogv1' in requirements or REVLOGV2_REQUIREMENT in requirements: |
|
604 options.update(resolverevlogstorevfsoptions(ui, requirements)) |
|
605 |
|
606 return options |
|
607 |
|
608 def resolverevlogstorevfsoptions(ui, requirements): |
|
609 """Resolve opener options specific to revlogs.""" |
|
610 |
|
611 options = {} |
|
612 |
|
613 if b'revlogv1' in requirements: |
|
614 options[b'revlogv1'] = True |
|
615 if REVLOGV2_REQUIREMENT in requirements: |
|
616 options[b'revlogv2'] = True |
|
617 |
|
618 if b'generaldelta' in requirements: |
|
619 options[b'generaldelta'] = True |
|
620 |
|
621 # experimental config: format.chunkcachesize |
|
622 chunkcachesize = ui.configint(b'format', b'chunkcachesize') |
|
623 if chunkcachesize is not None: |
|
624 options[b'chunkcachesize'] = chunkcachesize |
|
625 |
|
626 deltabothparents = ui.configbool(b'storage', |
|
627 b'revlog.optimize-delta-parent-choice') |
|
628 options[b'deltabothparents'] = deltabothparents |
|
629 |
|
630 options[b'lazydeltabase'] = not scmutil.gddeltaconfig(ui) |
|
631 |
|
632 chainspan = ui.configbytes(b'experimental', b'maxdeltachainspan') |
|
633 if 0 <= chainspan: |
|
634 options[b'maxdeltachainspan'] = chainspan |
|
635 |
|
636 mmapindexthreshold = ui.configbytes(b'experimental', |
|
637 b'mmapindexthreshold') |
|
638 if mmapindexthreshold is not None: |
|
639 options[b'mmapindexthreshold'] = mmapindexthreshold |
|
640 |
|
641 withsparseread = ui.configbool(b'experimental', b'sparse-read') |
|
642 srdensitythres = float(ui.config(b'experimental', |
|
643 b'sparse-read.density-threshold')) |
|
644 srmingapsize = ui.configbytes(b'experimental', |
|
645 b'sparse-read.min-gap-size') |
|
646 options[b'with-sparse-read'] = withsparseread |
|
647 options[b'sparse-read-density-threshold'] = srdensitythres |
|
648 options[b'sparse-read-min-gap-size'] = srmingapsize |
|
649 |
|
650 sparserevlog = SPARSEREVLOG_REQUIREMENT in requirements |
|
651 options[b'sparse-revlog'] = sparserevlog |
|
652 if sparserevlog: |
|
653 options[b'generaldelta'] = True |
|
654 |
|
655 maxchainlen = None |
|
656 if sparserevlog: |
|
657 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH |
|
658 # experimental config: format.maxchainlen |
|
659 maxchainlen = ui.configint(b'format', b'maxchainlen', maxchainlen) |
|
660 if maxchainlen is not None: |
|
661 options[b'maxchainlen'] = maxchainlen |
|
662 |
|
663 for r in requirements: |
|
664 if r.startswith(b'exp-compression-'): |
|
665 options[b'compengine'] = r[len(b'exp-compression-'):] |
|
666 |
|
667 return options |
580 |
668 |
581 @interfaceutil.implementer(repository.completelocalrepository) |
669 @interfaceutil.implementer(repository.completelocalrepository) |
582 class localrepository(object): |
670 class localrepository(object): |
583 |
671 |
584 # obsolete experimental requirements: |
672 # obsolete experimental requirements: |
710 self.ui.configbool('devel', 'check-locks')): |
793 self.ui.configbool('devel', 'check-locks')): |
711 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs |
794 if util.safehasattr(self.svfs, 'vfs'): # this is filtervfs |
712 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit) |
795 self.svfs.vfs.audit = self._getsvfsward(self.svfs.vfs.audit) |
713 else: # standard vfs |
796 else: # standard vfs |
714 self.svfs.audit = self._getsvfsward(self.svfs.audit) |
797 self.svfs.audit = self._getsvfsward(self.svfs.audit) |
715 self._applyopenerreqs() |
|
716 |
798 |
717 self._dirstatevalidatewarned = False |
799 self._dirstatevalidatewarned = False |
718 |
800 |
719 self._branchcaches = {} |
801 self._branchcaches = {} |
720 self._revbranchcache = None |
802 self._revbranchcache = None |
814 caps = set(caps) |
896 caps = set(caps) |
815 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self, |
897 capsblob = bundle2.encodecaps(bundle2.getrepocaps(self, |
816 role='client')) |
898 role='client')) |
817 caps.add('bundle2=' + urlreq.quote(capsblob)) |
899 caps.add('bundle2=' + urlreq.quote(capsblob)) |
818 return caps |
900 return caps |
819 |
|
820 def _applyopenerreqs(self): |
|
821 self.svfs.options = {r: True for r in self.requirements |
|
822 if r in self.openerreqs} |
|
823 # experimental config: format.chunkcachesize |
|
824 chunkcachesize = self.ui.configint('format', 'chunkcachesize') |
|
825 if chunkcachesize is not None: |
|
826 self.svfs.options['chunkcachesize'] = chunkcachesize |
|
827 # experimental config: format.manifestcachesize |
|
828 manifestcachesize = self.ui.configint('format', 'manifestcachesize') |
|
829 if manifestcachesize is not None: |
|
830 self.svfs.options['manifestcachesize'] = manifestcachesize |
|
831 deltabothparents = self.ui.configbool('storage', |
|
832 'revlog.optimize-delta-parent-choice') |
|
833 self.svfs.options['deltabothparents'] = deltabothparents |
|
834 self.svfs.options['lazydeltabase'] = not scmutil.gddeltaconfig(self.ui) |
|
835 chainspan = self.ui.configbytes('experimental', 'maxdeltachainspan') |
|
836 if 0 <= chainspan: |
|
837 self.svfs.options['maxdeltachainspan'] = chainspan |
|
838 mmapindexthreshold = self.ui.configbytes('experimental', |
|
839 'mmapindexthreshold') |
|
840 if mmapindexthreshold is not None: |
|
841 self.svfs.options['mmapindexthreshold'] = mmapindexthreshold |
|
842 withsparseread = self.ui.configbool('experimental', 'sparse-read') |
|
843 srdensitythres = float(self.ui.config('experimental', |
|
844 'sparse-read.density-threshold')) |
|
845 srmingapsize = self.ui.configbytes('experimental', |
|
846 'sparse-read.min-gap-size') |
|
847 self.svfs.options['with-sparse-read'] = withsparseread |
|
848 self.svfs.options['sparse-read-density-threshold'] = srdensitythres |
|
849 self.svfs.options['sparse-read-min-gap-size'] = srmingapsize |
|
850 sparserevlog = SPARSEREVLOG_REQUIREMENT in self.requirements |
|
851 self.svfs.options['sparse-revlog'] = sparserevlog |
|
852 if sparserevlog: |
|
853 self.svfs.options['generaldelta'] = True |
|
854 maxchainlen = None |
|
855 if sparserevlog: |
|
856 maxchainlen = revlogconst.SPARSE_REVLOG_MAX_CHAIN_LENGTH |
|
857 # experimental config: format.maxchainlen |
|
858 maxchainlen = self.ui.configint('format', 'maxchainlen', maxchainlen) |
|
859 if maxchainlen is not None: |
|
860 self.svfs.options['maxchainlen'] = maxchainlen |
|
861 |
|
862 for r in self.requirements: |
|
863 if r.startswith('exp-compression-'): |
|
864 self.svfs.options['compengine'] = r[len('exp-compression-'):] |
|
865 |
|
866 # TODO move "revlogv2" to openerreqs once finalized. |
|
867 if REVLOGV2_REQUIREMENT in self.requirements: |
|
868 self.svfs.options['revlogv2'] = True |
|
869 |
901 |
870 def _writerequirements(self): |
902 def _writerequirements(self): |
871 scmutil.writerequires(self.vfs, self.requirements) |
903 scmutil.writerequires(self.vfs, self.requirements) |
872 |
904 |
873 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle: |
905 # Don't cache auditor/nofsauditor, or you'll end up with reference cycle: |