##// END OF EJS Templates
localrepo: automatically load lfs extension when required (BC)...
localrepo: automatically load lfs extension when required (BC) If an unrecognized requirement is present (possibly due to an unloaded extension), the user will get an error message telling them to go to https://mercurial-scm.org/wiki/MissingRequirement for more info. And some requirements clearly map to known extensions shipped by Mercurial. This commit teaches repository loading to automatically map requirements to extensions. We implement support for loading the lfs extension when the "lfs" requirement is present. This behavior feels more user-friendly to me and I'm having trouble coming up with a compelling reason to not do it. The strongest argument I have against is that - strictly speaking - requirements are general repository features and there could be N providers of that feature. e.g. in the case of LFS, there could be another extension implementing LFS support. And the user would want to use this non-official extension rather than the built-in one. The way this patch implements things, the non-official extension could be missing and Mercurial would load the official lfs extension, leading to unexpected behavior. But this feels like a highly marginal use case to me and doesn't outweigh the user benefit of "it just works." If someone really wanted to e.g. use a custom LFS extension, they could prevent the built-in one from being loaded by either defining "extensions.lfs=/path/to/custom/extension" or "extensions.lfs=!", as the automatic extension loading only occurs if there is no config entry for that extension. Differential Revision: https://phab.mercurial-scm.org/D4711

File last commit:

r34398:765eb17a default
r39888:2c2fadbc default
Show More
_compat.py
90 lines | 2.8 KiB | text/x-python | PythonLexer
from __future__ import absolute_import, division, print_function
import sys
import types
PY2 = sys.version_info[0] == 2
if PY2:
from UserDict import IterableUserDict
# We 'bundle' isclass instead of using inspect as importing inspect is
# fairly expensive (order of 10-15 ms for a modern machine in 2016)
def isclass(klass):
return isinstance(klass, (type, types.ClassType))
# TYPE is used in exceptions, repr(int) is different on Python 2 and 3.
TYPE = "type"
def iteritems(d):
return d.iteritems()
def iterkeys(d):
return d.iterkeys()
# Python 2 is bereft of a read-only dict proxy, so we make one!
class ReadOnlyDict(IterableUserDict):
"""
Best-effort read-only dict wrapper.
"""
def __setitem__(self, key, val):
# We gently pretend we're a Python 3 mappingproxy.
raise TypeError("'mappingproxy' object does not support item "
"assignment")
def update(self, _):
# We gently pretend we're a Python 3 mappingproxy.
raise AttributeError("'mappingproxy' object has no attribute "
"'update'")
def __delitem__(self, _):
# We gently pretend we're a Python 3 mappingproxy.
raise TypeError("'mappingproxy' object does not support item "
"deletion")
def clear(self):
# We gently pretend we're a Python 3 mappingproxy.
raise AttributeError("'mappingproxy' object has no attribute "
"'clear'")
def pop(self, key, default=None):
# We gently pretend we're a Python 3 mappingproxy.
raise AttributeError("'mappingproxy' object has no attribute "
"'pop'")
def popitem(self):
# We gently pretend we're a Python 3 mappingproxy.
raise AttributeError("'mappingproxy' object has no attribute "
"'popitem'")
def setdefault(self, key, default=None):
# We gently pretend we're a Python 3 mappingproxy.
raise AttributeError("'mappingproxy' object has no attribute "
"'setdefault'")
def __repr__(self):
# Override to be identical to the Python 3 version.
return "mappingproxy(" + repr(self.data) + ")"
def metadata_proxy(d):
res = ReadOnlyDict()
res.data.update(d) # We blocked update, so we have to do it like this.
return res
else:
def isclass(klass):
return isinstance(klass, type)
TYPE = "class"
def iteritems(d):
return d.items()
def iterkeys(d):
return d.keys()
def metadata_proxy(d):
return types.MappingProxyType(dict(d))