##// END OF EJS Templates
persistent-nodemap: properly ignore non-existent `.nd` data file...
persistent-nodemap: properly ignore non-existent `.nd` data file This code was meant to handle the case of a nodemap docket file pointing to a nodemap data file that doesn’t exist (anymore), but most likely caused an `UnboundLocalError` exception instead when `data` was used on the next line without being defined. This case is theoretically possible with a race condition between two hg processes, but is hard to reproduce or test: * Process A reads a docket file and finds a UID in it that points to a given data file name. * Process B decides that this same data file needs compacting. It writes a new one with a different UID, overwrites the docket file, then removes the old data file. * Only then process A tries to a open a file that doesn’t exist anymore. Differential Revision: https://phab.mercurial-scm.org/D9533

File last commit:

r34398:765eb17a default
r46705:8ff2d835 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))