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


Reply via email to