From 6dc2a3ef1ffac9eab3728d37a3f6e133ac34ab27 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Tue, 4 Nov 2008 07:40:34 +0000 Subject: Bug #245362 - Use tuples of (device, inode) for all path comparisons inside LinkageMap, so that they work regardless of path differences due to symlinked directories. TODO: Fix other preserve-libs code, such as dblink._preserve_libs(), to use this approach for path comparisons. svn path=/main/trunk/; revision=11806 --- pym/portage/dbapi/vartree.py | 51 +++++++++++++++++++++++++++----------------- pym/portage/util.py | 6 +----- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py index 0361bb3d9..f88431ee0 100644 --- a/pym/portage/dbapi/vartree.py +++ b/pym/portage/dbapi/vartree.py @@ -149,8 +149,23 @@ class LinkageMap(object): self._root = self._dbapi.root self._libs = {} self._obj_properties = {} - self._defpath = set(getlibpaths(self._root)) self._obj_key_cache = {} + self._defpath = set() + self._path_key_cache = {} + + def _clear_cache(self): + self._libs.clear() + self._obj_properties.clear() + self._obj_key_cache.clear() + self._defpath.clear() + self._path_key_cache.clear() + + def _path_key(self, path): + key = self._path_key_cache.get(path) + if key is None: + key = self._ObjectKey(path, self._root) + self._path_key_cache[path] = key + return key class _ObjectKey(object): @@ -222,10 +237,12 @@ class LinkageMap(object): def rebuild(self, exclude_pkgs=None, include_file=None): root = self._root - self._defpath = set(getlibpaths(root)) - libs = {} - obj_key_cache = {} - obj_properties = {} + self._clear_cache() + self._defpath.update(getlibpaths(self._root)) + libs = self._libs + obj_key_cache = self._obj_key_cache + obj_properties = self._obj_properties + lines = [] for cpv in self._dbapi.cpv_all(): if exclude_pkgs is not None and cpv in exclude_pkgs: @@ -259,8 +276,7 @@ class LinkageMap(object): obj = fields[1] obj_key = self._ObjectKey(obj, root) soname = fields[2] - path = set([ - normalize_path(os.path.join(self._root, x.lstrip(os.path.sep))) + path = set([normalize_path(x) \ for x in filter(None, fields[3].replace( "${ORIGIN}", os.path.dirname(obj)).replace( "$ORIGIN", os.path.dirname(obj)).split(":"))]) @@ -281,10 +297,6 @@ class LinkageMap(object): obj_properties.setdefault(obj_key, \ (arch, needed, path, soname, set()))[4].add(obj) - self._libs = libs - self._obj_properties = obj_properties - self._obj_key_cache = obj_key_cache - def listBrokenBinaries(self, debug=False): """ Find binaries and their needed sonames, which have no providers. @@ -530,7 +542,7 @@ class LinkageMap(object): raise KeyError("%s (%s) not in object list" % (obj_key, obj)) arch, needed, path, _, _ = self._obj_properties[obj_key] - path = path.union(self._defpath) + path_keys = set(self._path_key(x) for x in path.union(self._defpath)) for soname in needed: rValue[soname] = set() if soname not in self._libs or arch not in self._libs[soname]: @@ -540,8 +552,7 @@ class LinkageMap(object): for provider_key in self._libs[soname][arch]["providers"]: providers = self._obj_properties[provider_key][4] for provider in providers: - if os.path.join(self._root, - os.path.dirname(provider).lstrip(os.path.sep)) in path: + if self._path_key(os.path.dirname(provider)) in path_keys: rValue[soname].add(provider) return rValue @@ -584,10 +595,6 @@ class LinkageMap(object): if obj_key not in self._obj_properties: raise KeyError("%s (%s) not in object list" % (obj_key, obj)) - # Determine the directory(ies) from the set of objects. - objs_dirs = set(os.path.join(self._root, - os.path.dirname(x).lstrip(os.sep)) for x in objs) - # If there is another version of this lib with the # same soname and the master link points to that # other version, this lib will be shadowed and won't @@ -606,6 +613,10 @@ class LinkageMap(object): (master_st.st_dev, master_st.st_ino): return set() + # Determine the directory(ies) from the set of objects. + objs_dir_keys = set(self._path_key(os.path.dirname(x)) for x in objs) + defpath_keys = set(self._path_key(x) for x in self._defpath) + arch, _, _, soname, _ = self._obj_properties[obj_key] if soname in self._libs and arch in self._libs[soname]: # For each potential consumer, add it to rValue if an object from the @@ -613,8 +624,8 @@ class LinkageMap(object): for consumer_key in self._libs[soname][arch]["consumers"]: _, _, path, _, consumer_objs = \ self._obj_properties[consumer_key] - path = path.union(self._defpath) - if objs_dirs.intersection(path): + path_keys = defpath_keys.union(self._path_key(x) for x in path) + if objs_dir_keys.intersection(path_keys): rValue.update(consumer_objs) return rValue diff --git a/pym/portage/util.py b/pym/portage/util.py index 481c15bbc..ab7214070 100644 --- a/pym/portage/util.py +++ b/pym/portage/util.py @@ -1208,8 +1208,4 @@ def getlibpaths(root): rval.append("/usr/lib") rval.append("/lib") - rval = [normalize_path(os.path.join(root, x.lstrip(os.path.sep))) \ - for x in rval if x] - - return rval - + return [normalize_path(x) for x in rval if x] -- cgit v1.2.3-1-g7c22