Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11740 - main/trunk/pym/portage/dbapi
Date: Tue, 28 Oct 2008 23:04:19
Message-Id: E1Kuxbi-0006f0-Rh@stork.gentoo.org
1 Author: zmedico
2 Date: 2008-10-28 23:04:14 +0000 (Tue, 28 Oct 2008)
3 New Revision: 11740
4
5 Modified:
6 main/trunk/pym/portage/dbapi/vartree.py
7 Log:
8 Bug #238957 - When removing unneeded preserved libs inside dblink.unmerge(),
9 use a digraph to properly track consumer relationships between preserved libs.
10 This fixes cases where preserved libs failed to be removed due to being
11 consumed by other preserved libs.
12
13
14 Modified: main/trunk/pym/portage/dbapi/vartree.py
15 ===================================================================
16 --- main/trunk/pym/portage/dbapi/vartree.py 2008-10-28 21:22:22 UTC (rev 11739)
17 +++ main/trunk/pym/portage/dbapi/vartree.py 2008-10-28 23:04:14 UTC (rev 11740)
18 @@ -23,7 +23,7 @@
19 grabfile, grabdict, normalize_path, new_protect_filename, getlibpaths
20 from portage.versions import pkgsplit, catpkgsplit, catsplit, best, pkgcmp
21
22 -from portage import listdir, dep_expand, flatten, key_expand, \
23 +from portage import listdir, dep_expand, digraph, flatten, key_expand, \
24 doebuild_environment, doebuild, env_update, prepare_build_dirs, \
25 abssymlink, movefile, _movefile, bsd_chflags, cpv_getkey
26
27 @@ -208,6 +208,16 @@
28 """
29 return isinstance(self._key, tuple)
30
31 + class _LibGraphNode(_ObjectKey):
32 + __slots__ = ("alt_paths",)
33 +
34 + def __init__(self, obj, root):
35 + LinkageMap._ObjectKey.__init__(self, obj, root)
36 + self.alt_paths = set()
37 +
38 + def __str__(self):
39 + return str(sorted(self.alt_paths))
40 +
41 def rebuild(self, include_file=None):
42 root = self._root
43 libs = {}
44 @@ -1906,7 +1916,8 @@
45 writemsg("!!! FAILED prerm: %s\n" % retval, noiselevel=-1)
46
47 self._unmerge_pkgfiles(pkgfiles, others_in_slot)
48 -
49 + self._clear_contents_cache()
50 +
51 # Remove the registration of preserved libs for this pkg instance
52 plib_registry = self.vartree.dbapi.plib_registry
53 plib_registry.unregister(self.mycpv, self.settings["SLOT"],
54 @@ -1930,60 +1941,64 @@
55 self.vartree.dbapi.linkmap.rebuild()
56
57 # remove preserved libraries that don't have any consumers left
58 - # FIXME: this code is quite ugly and can likely be optimized in several ways
59 + # Since preserved libraries can be consumers of other preserved
60 + # libraries, use a graph to track consumer relationships.
61 plib_dict = plib_registry.getPreservedLibs()
62 - for cpv in plib_dict:
63 - plib_dict[cpv].sort()
64 - # for the loop below to work correctly, we need all
65 - # symlinks to come before the actual files, such that
66 - # the recorded symlinks (sonames) will be resolved into
67 - # their real target before the object is found not to be
68 - # in the reverse NEEDED map
69 - def symlink_compare(x, y):
70 - x = os.path.join(self.myroot, x.lstrip(os.path.sep))
71 - y = os.path.join(self.myroot, y.lstrip(os.path.sep))
72 - if os.path.islink(x):
73 - if os.path.islink(y):
74 - return 0
75 - else:
76 - return -1
77 - elif os.path.islink(y):
78 - return 1
79 + lib_graph = digraph()
80 + preserved_nodes = set()
81 + root = self.myroot
82 + for plibs in plib_dict.itervalues():
83 + for f in plibs:
84 + preserved_node = LinkageMap._LibGraphNode(f, root)
85 + if not preserved_node.file_exists():
86 + continue
87 + existing_node = lib_graph.get(preserved_node)
88 + if existing_node is not None:
89 + preserved_node = existing_node
90 else:
91 - return 0
92 + lib_graph.add(preserved_node, None)
93 + preserved_node.alt_paths.add(f)
94 + preserved_nodes.add(preserved_node)
95 + for c in self.vartree.dbapi.linkmap.findConsumers(f):
96 + if self.isowner(c, root):
97 + # TODO: Remove this case since it shouldn't be
98 + # necessary. This seems to be a false positive
99 + # returned from LinkageMap.findConsumers().
100 + continue
101 + consumer_node = LinkageMap._LibGraphNode(c, root)
102 + if not consumer_node.file_exists():
103 + continue
104 + # Note that consumers may also be providers.
105 + existing_node = lib_graph.get(consumer_node)
106 + if existing_node is not None:
107 + consumer_node = existing_node
108 + consumer_node.alt_paths.add(c)
109 + lib_graph.add(preserved_node, consumer_node)
110
111 - plib_dict[cpv].sort(symlink_compare)
112 - for f in plib_dict[cpv]:
113 - f_abs = os.path.join(self.myroot, f.lstrip(os.path.sep))
114 - if not os.path.exists(f_abs):
115 - continue
116 - unlink_list = []
117 - consumers = self.vartree.dbapi.linkmap.findConsumers(f)
118 - if not consumers:
119 - unlink_list.append(f_abs)
120 + while not lib_graph.empty():
121 + root_nodes = preserved_nodes.intersection(lib_graph.root_nodes())
122 + if not root_nodes:
123 + break
124 + lib_graph.difference_update(root_nodes)
125 + unlink_list = set()
126 + for node in root_nodes:
127 + unlink_list.update(node.alt_paths)
128 + unlink_list = sorted(unlink_list)
129 + for obj in unlink_list:
130 + obj = os.path.join(root, obj.lstrip(os.sep))
131 + if os.path.islink(obj):
132 + obj_type = "sym"
133 else:
134 - keep=False
135 - for c in consumers:
136 - c = os.path.join(self.myroot,
137 - c.lstrip(os.path.sep))
138 - if c not in self.getcontents():
139 - keep=True
140 - break
141 - if not keep:
142 - unlink_list.append(f_abs)
143 - for obj in unlink_list:
144 - try:
145 - if os.path.islink(obj):
146 - obj_type = "sym"
147 - else:
148 - obj_type = "obj"
149 - os.unlink(obj)
150 - showMessage("<<< !needed %s %s\n" % (obj_type, obj))
151 - except OSError, e:
152 - if e.errno == errno.ENOENT:
153 - pass
154 - else:
155 - raise e
156 + obj_type = "obj"
157 + try:
158 + os.unlink(obj)
159 + except OSError, e:
160 + if e.errno != errno.ENOENT:
161 + raise
162 + del e
163 + else:
164 + showMessage("<<< !needed %s %s\n" % (obj_type, obj))
165 +
166 plib_registry.pruneNonExisting()
167
168 finally: