Fix interaction between LinkageMap.rebuild() and the package replacement
authorZac Medico <zmedico@gentoo.org>
Wed, 29 Oct 2008 00:07:34 +0000 (00:07 -0000)
committerZac Medico <zmedico@gentoo.org>
Wed, 29 Oct 2008 00:07:34 +0000 (00:07 -0000)
process in order to avoid problems with stale or unaccounted NEEDED. This
solves a LinkageMap corruption issue which caused findConsumers to return
false positive inside dblink.unmerge().

svn path=/main/trunk/; revision=11742

pym/portage/dbapi/vartree.py

index 57dba00a134bdffa97274569fc64d24c865a4e71..9a77ce085b8f53b7c69877e1104e2c95b5ae5206 100644 (file)
@@ -218,13 +218,15 @@ class LinkageMap(object):
                def __str__(self):
                        return str(sorted(self.alt_paths))
 
-       def rebuild(self, include_file=None):
+       def rebuild(self, exclude_pkgs=None, include_file=None):
                root = self._root
                libs = {}
                obj_key_cache = {}
                obj_properties = {}
                lines = []
                for cpv in self._dbapi.cpv_all():
+                       if exclude_pkgs is not None and cpv in exclude_pkgs:
+                               continue
                        lines += self._dbapi.aux_get(cpv, ["NEEDED.ELF.2"])[0].split('\n')
                # Cache NEEDED.* files avoid doing excessive IO for every rebuild.
                self._dbapi.flush_cache()
@@ -1938,8 +1940,12 @@ class dblink(object):
                                if retval != os.EX_OK:
                                        writemsg("!!! FAILED postrm: %s\n" % retval, noiselevel=-1)
 
-                       # regenerate reverse NEEDED map
-                       self.vartree.dbapi.linkmap.rebuild()
+                       # Skip this if another package in the same slot has just been
+                       # merged on top of this package, since the other package has
+                       # already called LinkageMap.rebuild() and passed it's NEEDED file
+                       # in as an argument.
+                       if not others_in_slot:
+                               self.vartree.dbapi.linkmap.rebuild(exclude_pkgs=(self.mycpv,))
 
                        # remove preserved libraries that don't have any consumers left
                        # Since preserved libraries can be consumers of other preserved
@@ -1961,11 +1967,6 @@ class dblink(object):
                                        preserved_node.alt_paths.add(f)
                                        preserved_nodes.add(preserved_node)
                                        for c in self.vartree.dbapi.linkmap.findConsumers(f):
-                                               if self.isowner(c, root):
-                                                       # TODO: Remove this case since it shouldn't be
-                                                       # necessary. This seems to be a false positive
-                                                       # returned from LinkageMap.findConsumers().
-                                                       continue
                                                consumer_node = LinkageMap._LibGraphNode(c, root)
                                                if not consumer_node.file_exists():
                                                        continue
@@ -3126,6 +3127,10 @@ class dblink(object):
                                gid=portage_gid, mode=02750, mask=02)
                        writedict(cfgfiledict, conf_mem_file)
 
+               exclude_pkgs = set(dblnk.mycpv for dblnk in others_in_slot)
+               self.vartree.dbapi.linkmap.rebuild(exclude_pkgs=exclude_pkgs,
+                       include_file=os.path.join(inforoot, "NEEDED.ELF.2"))
+
                # These caches are populated during collision-protect and the data
                # they contain is now invalid. It's very important to invalidate
                # the contents_inodes cache so that FEATURES=unmerge-orphans