##// END OF EJS Templates
cmdutil: convert _revertprefetch() to a generic stored file hook (API)...
cmdutil: convert _revertprefetch() to a generic stored file hook (API) This will be used by LFS to fetch required files in a group for multiple commands, prior to being accessed. That avoids the one-at-a-time fetch when the filelog wrapper goes to access it, and it is missing locally (which costs two round trips to the server.) The core command list that needs this is probably at least: - annotate - archive (which is also used by extdiff) - cat - diff - export - grep - verify (sadly) - anything that has the '{data}' template There are no core users of the revert prefetch hook, and never have been since it was introduced in 45e02cfad4bd for remotefilelog. Thanks to Yuya for figuring out a way to reliably trigger the deprecated warning. Unfortunately, it wanted to blame the caller of revert. Passing along an adjusted stack level seemed the least bad choice (although it still blames a core function). One thing to note is that the store lock isn't being held when this is called. I'm not at all familiar with remotefilelog or its locking requirements, so this may not be a big deal. Currently, LFS doesn't hold a lock when downloading files. Even though largefiles doesn't either, I'm starting to think it should, and maybe the .hg/store/lock isn't good enough to cover the globally shared cache. .. api:: The cmdutil._revertprefetch() hook point for prefetching stored files has been replaced by the command agnostic cmdutil._prefetchfiles(). The new function takes a list of files, instead of a list of lists of files.

File last commit:

r35476:8652ab40 default
r35941:efbd0423 default
Show More
policy.py
116 lines | 3.8 KiB | text/x-python | PythonLexer
# policy.py - module policy logic for Mercurial.
#
# Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import os
import sys
# Rules for how modules can be loaded. Values are:
#
# c - require C extensions
# allow - allow pure Python implementation when C loading fails
# cffi - required cffi versions (implemented within pure module)
# cffi-allow - allow pure Python implementation if cffi version is missing
# py - only load pure Python modules
#
# By default, fall back to the pure modules so the in-place build can
# run without recompiling the C extensions. This will be overridden by
# __modulepolicy__ generated by setup.py.
policy = b'allow'
_packageprefs = {
# policy: (versioned package, pure package)
b'c': (r'cext', None),
b'allow': (r'cext', r'pure'),
b'cffi': (r'cffi', None),
b'cffi-allow': (r'cffi', r'pure'),
b'py': (None, r'pure'),
}
try:
from . import __modulepolicy__
policy = __modulepolicy__.modulepolicy
except ImportError:
pass
# PyPy doesn't load C extensions.
#
# The canonical way to do this is to test platform.python_implementation().
# But we don't import platform and don't bloat for it here.
if r'__pypy__' in sys.builtin_module_names:
policy = b'cffi'
# Our C extensions aren't yet compatible with Python 3. So use pure Python
# on Python 3 for now.
if sys.version_info[0] >= 3:
policy = b'py'
# Environment variable can always force settings.
if sys.version_info[0] >= 3:
if r'HGMODULEPOLICY' in os.environ:
policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
else:
policy = os.environ.get(r'HGMODULEPOLICY', policy)
def _importfrom(pkgname, modname):
# from .<pkgname> import <modname> (where . is looked through this module)
fakelocals = {}
pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
try:
fakelocals[modname] = mod = getattr(pkg, modname)
except AttributeError:
raise ImportError(r'cannot import name %s' % modname)
# force import; fakelocals[modname] may be replaced with the real module
getattr(mod, r'__doc__', None)
return fakelocals[modname]
# keep in sync with "version" in C modules
_cextversions = {
(r'cext', r'base85'): 1,
(r'cext', r'bdiff'): 1,
(r'cext', r'diffhelpers'): 1,
(r'cext', r'mpatch'): 1,
(r'cext', r'osutil'): 3,
(r'cext', r'parsers'): 4,
}
# map import request to other package or module
_modredirects = {
(r'cext', r'charencode'): (r'cext', r'parsers'),
(r'cffi', r'base85'): (r'pure', r'base85'),
(r'cffi', r'charencode'): (r'pure', r'charencode'),
(r'cffi', r'diffhelpers'): (r'pure', r'diffhelpers'),
(r'cffi', r'parsers'): (r'pure', r'parsers'),
}
def _checkmod(pkgname, modname, mod):
expected = _cextversions.get((pkgname, modname))
actual = getattr(mod, r'version', None)
if actual != expected:
raise ImportError(r'cannot import module %s.%s '
r'(expected version: %d, actual: %r)'
% (pkgname, modname, expected, actual))
def importmod(modname):
"""Import module according to policy and check API version"""
try:
verpkg, purepkg = _packageprefs[policy]
except KeyError:
raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
assert verpkg or purepkg
if verpkg:
pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname))
try:
mod = _importfrom(pn, mn)
if pn == verpkg:
_checkmod(pn, mn, mod)
return mod
except ImportError:
if not purepkg:
raise
pn, mn = _modredirects.get((purepkg, modname), (purepkg, modname))
return _importfrom(pn, mn)