This adds a dblink._contents attribute with methods that provide an interface for contents operations with "implicit" case handling. The new methods are implemented in a separate ContentsCaseSensitivityManager class, in order to avoid adding more bloat to vartree.py.
X-Gentoo-Bug: 524236 X-Gentoo-Url: https://bugs.gentoo.org/show_bug.cgi?id=524236 --- .../dbapi/_ContentsCaseSensitivityManager.py | 93 ++++++++++++++++++++++ pym/portage/dbapi/vartree.py | 3 + 2 files changed, 96 insertions(+) create mode 100644 pym/portage/dbapi/_ContentsCaseSensitivityManager.py diff --git a/pym/portage/dbapi/_ContentsCaseSensitivityManager.py b/pym/portage/dbapi/_ContentsCaseSensitivityManager.py new file mode 100644 index 0000000..c479ec9 --- /dev/null +++ b/pym/portage/dbapi/_ContentsCaseSensitivityManager.py @@ -0,0 +1,93 @@ +# Copyright 2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +class ContentsCaseSensitivityManager(object): + """ + Implicitly handles case transformations that are needed for + case-insensitive support. + """ + + def __init__(self, db): + """ + @param db: A dblink instance + @type db: vartree.dblink + """ + self.getcontents = db.getcontents + + if "case-insensitive-fs" in db.settings.features: + self.unmap_key = self._unmap_key_case_insensitive + self.contains = self._contains_case_insensitive + self.keys = self._keys_case_insensitive + + self._contents_insensitive = None + self._reverse_key_map = None + + def clear_cache(self): + """ + Clear all cached contents data. + """ + self._contents_insensitive = None + self._reverse_key_map = None + + def keys(self): + """ + Iterate over all contents keys, which are transformed to + lowercase when appropriate, for use in case-insensitive + comparisons. + @rtype: iterator + @return: An iterator over all the contents keys + """ + return iter(self.getcontents()) + + def contains(self, key): + """ + Check if the given key is contained in the contents, using + case-insensitive comparison when appropriate. + @param key: A filesystem path (including ROOT and EPREFIX) + @type key: str + @rtype: bool + @return: True if the given key is contained in the contents, + False otherwise + """ + return key in self.getcontents() + + def unmap_key(self, key): + """ + Map a key (from the keys method) back to its case-preserved + form. + @param key: A filesystem path (including ROOT and EPREFIX) + @type key: str + @rtype: str + @return: The case-preserved form of key + """ + return key + + def _case_insensitive_init(self): + """ + Initialize data structures for case-insensitive support. + """ + self._contents_insensitive = dict( + (k.lower(), v) for k, v in self.getcontents().items()) + self._reverse_key_map = dict( + (k.lower(), k) for k in self.getcontents()) + + def _keys_case_insensitive(self): + if self._contents_insensitive is None: + self._case_insensitive_init() + return iter(self._contents_insensitive) + + _keys_case_insensitive.__doc__ = keys.__doc__ + + def _contains_case_insensitive(self, key): + if self._contents_insensitive is None: + self._case_insensitive_init() + return key.lower() in self._contents_insensitive + + _contains_case_insensitive.__doc__ = contains.__doc__ + + def _unmap_key_case_insensitive(self, key): + if self._reverse_key_map is None: + self._case_insensitive_init() + return self._reverse_key_map[key] + + _unmap_key_case_insensitive.__doc__ = unmap_key.__doc__ diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 8b06f4c..81059b1 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -69,6 +69,7 @@ from _emerge.EbuildPhase import EbuildPhase from _emerge.emergelog import emergelog from _emerge.MiscFunctionsProcess import MiscFunctionsProcess from _emerge.SpawnProcess import SpawnProcess +from ._ContentsCaseSensitivityManager import ContentsCaseSensitivityManager import errno import fnmatch @@ -1525,6 +1526,7 @@ class dblink(object): # When necessary, this attribute is modified for # compliance with RESTRICT=preserve-libs. self._preserve_libs = "preserve-libs" in mysettings.features + self._contents = ContentsCaseSensitivityManager(self) def __hash__(self): return hash(self._hash_key) @@ -1612,6 +1614,7 @@ class dblink(object): self.contentscache = None self._contents_inodes = None self._contents_basenames = None + self._contents.clear_cache() def getcontents(self): """ -- 2.0.4