Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11748 - main/trunk/pym/portage/dbapi
Date: Thu, 30 Oct 2008 07:46:36
Message-Id: E1KvSEi-0006pz-Mt@stork.gentoo.org
1 Author: zmedico
2 Date: 2008-10-30 07:46:32 +0000 (Thu, 30 Oct 2008)
3 New Revision: 11748
4
5 Modified:
6 main/trunk/pym/portage/dbapi/vartree.py
7 Log:
8 Bug # 225429 - Try to remove unneeded preserved libs just before returning
9 from dblink.treewalk(), after the library path has been updated. This is
10 intended to remove unneeded preserved libs after a gcc upgrade. TODO: Figure
11 out why libgomp.so.1 still isn't properly removed.
12
13
14 Modified: main/trunk/pym/portage/dbapi/vartree.py
15 ===================================================================
16 --- main/trunk/pym/portage/dbapi/vartree.py 2008-10-30 03:37:55 UTC (rev 11747)
17 +++ main/trunk/pym/portage/dbapi/vartree.py 2008-10-30 07:46:32 UTC (rev 11748)
18 @@ -1953,118 +1953,21 @@
19 self.vartree.dbapi.linkmap.rebuild(exclude_pkgs=(self.mycpv,))
20
21 # remove preserved libraries that don't have any consumers left
22 - # Since preserved libraries can be consumers of other preserved
23 - # libraries, use a graph to track consumer relationships.
24 - plib_dict = plib_registry.getPreservedLibs()
25 - lib_graph = digraph()
26 - preserved_nodes = set()
27 - preserved_paths = set()
28 - path_cpv_map = {}
29 - path_node_map = {}
30 - root = self.myroot
31 -
32 - def path_to_node(path):
33 - node = path_node_map.get(path)
34 - if node is None:
35 - node = LinkageMap._LibGraphNode(path, root)
36 - alt_path_node = lib_graph.get(node)
37 - if alt_path_node is not None:
38 - node = alt_path_node
39 - node.alt_paths.add(path)
40 - path_node_map[path] = node
41 - return node
42 -
43 - linkmap = self.vartree.dbapi.linkmap
44 - for cpv, plibs in plib_dict.iteritems():
45 - for f in plibs:
46 - path_cpv_map[f] = cpv
47 - preserved_node = path_to_node(f)
48 - if not preserved_node.file_exists():
49 + cpv_lib_map = self._find_unused_preserved_libs()
50 + if cpv_lib_map:
51 + self._remove_preserved_libs(cpv_lib_map)
52 + for cpv, removed in cpv_lib_map.iteritems():
53 + if not self.vartree.dbapi.cpv_exists(cpv):
54 + for dblnk in others_in_slot:
55 + if dblnk.mycpv == cpv:
56 + # This one just got merged so it doesn't
57 + # register with cpv_exists() yet.
58 + self.vartree.dbapi.removeFromContents(
59 + dblnk, removed)
60 + break
61 continue
62 - lib_graph.add(preserved_node, None)
63 - preserved_paths.add(f)
64 - preserved_nodes.add(preserved_node)
65 - for c in self.vartree.dbapi.linkmap.findConsumers(f):
66 - consumer_node = path_to_node(c)
67 - if not consumer_node.file_exists():
68 - continue
69 - # Note that consumers may also be providers.
70 - lib_graph.add(preserved_node, consumer_node)
71 + self.vartree.dbapi.removeFromContents(cpv, removed)
72
73 - # Eliminate consumers having providers with the same soname as an
74 - # installed library that is not preserved. This eliminates
75 - # libraries that are erroneously preserved due to a move from one
76 - # directory to another.
77 - provider_cache = {}
78 - for preserved_node in preserved_nodes:
79 - soname = linkmap.getSoname(preserved_node)
80 - for consumer_node in lib_graph.parent_nodes(preserved_node):
81 - if consumer_node in preserved_nodes:
82 - continue
83 - providers = provider_cache.get(consumer_node)
84 - if providers is None:
85 - providers = linkmap.findProviders(consumer_node)
86 - provider_cache[consumer_node] = providers
87 - providers = providers.get(soname)
88 - if providers is None:
89 - continue
90 - for provider in providers:
91 - if provider in preserved_paths:
92 - continue
93 - provider_node = path_to_node(provider)
94 - if not provider_node.file_exists():
95 - continue
96 - if provider_node in preserved_nodes:
97 - continue
98 - # An alternative provider seems to be
99 - # installed, so drop this edge.
100 - lib_graph.remove_edge(preserved_node, consumer_node)
101 - break
102 -
103 - removed_for_cpv = {}
104 - while not lib_graph.empty():
105 - root_nodes = preserved_nodes.intersection(lib_graph.root_nodes())
106 - if not root_nodes:
107 - break
108 - lib_graph.difference_update(root_nodes)
109 - unlink_list = set()
110 - for node in root_nodes:
111 - unlink_list.update(node.alt_paths)
112 - unlink_list = sorted(unlink_list)
113 - for obj in unlink_list:
114 - cpv = path_cpv_map[obj]
115 - removed = removed_for_cpv.get(cpv)
116 - if removed is None:
117 - removed = set()
118 - removed_for_cpv[cpv] = removed
119 - removed.add(obj)
120 - obj = os.path.join(root, obj.lstrip(os.sep))
121 - if os.path.islink(obj):
122 - obj_type = "sym"
123 - else:
124 - obj_type = "obj"
125 - try:
126 - os.unlink(obj)
127 - except OSError, e:
128 - if e.errno != errno.ENOENT:
129 - raise
130 - del e
131 - else:
132 - showMessage("<<< !needed %s %s\n" % (obj_type, obj))
133 -
134 - for cpv, removed in removed_for_cpv.iteritems():
135 - if not self.vartree.dbapi.cpv_exists(cpv):
136 - for dblnk in others_in_slot:
137 - if dblnk.mycpv == cpv:
138 - # This one just got merged so it doesn't
139 - # register with cpv_exists() yet.
140 - self.vartree.dbapi.removeFromContents(dblnk, removed)
141 - break
142 - continue
143 - self.vartree.dbapi.removeFromContents(cpv, removed)
144 -
145 - plib_registry.pruneNonExisting()
146 -
147 finally:
148 if builddir_lock:
149 try:
150 @@ -2636,8 +2539,143 @@
151 # keep track of the libs we preserved
152 self.vartree.dbapi.plib_registry.register(self.mycpv, self.settings["SLOT"], counter, preserve_paths)
153
154 - del preserve_paths
155 -
156 + def _find_unused_preserved_libs(self):
157 + """
158 + Find preserved libraries that don't have any consumers left.
159 + """
160 +
161 + # Since preserved libraries can be consumers of other preserved
162 + # libraries, use a graph to track consumer relationships.
163 + plib_dict = self.vartree.dbapi.plib_registry.getPreservedLibs()
164 + lib_graph = digraph()
165 + preserved_nodes = set()
166 + preserved_paths = set()
167 + path_cpv_map = {}
168 + path_node_map = {}
169 + root = self.myroot
170 +
171 + def path_to_node(path):
172 + node = path_node_map.get(path)
173 + if node is None:
174 + node = LinkageMap._LibGraphNode(path, root)
175 + alt_path_node = lib_graph.get(node)
176 + if alt_path_node is not None:
177 + node = alt_path_node
178 + node.alt_paths.add(path)
179 + path_node_map[path] = node
180 + return node
181 +
182 + linkmap = self.vartree.dbapi.linkmap
183 + for cpv, plibs in plib_dict.iteritems():
184 + for f in plibs:
185 + path_cpv_map[f] = cpv
186 + preserved_node = path_to_node(f)
187 + if not preserved_node.file_exists():
188 + continue
189 + lib_graph.add(preserved_node, None)
190 + preserved_paths.add(f)
191 + preserved_nodes.add(preserved_node)
192 + for c in self.vartree.dbapi.linkmap.findConsumers(f):
193 + consumer_node = path_to_node(c)
194 + if not consumer_node.file_exists():
195 + continue
196 + # Note that consumers may also be providers.
197 + lib_graph.add(preserved_node, consumer_node)
198 +
199 + # Eliminate consumers having providers with the same soname as an
200 + # installed library that is not preserved. This eliminates
201 + # libraries that are erroneously preserved due to a move from one
202 + # directory to another.
203 + provider_cache = {}
204 + for preserved_node in preserved_nodes:
205 + soname = linkmap.getSoname(preserved_node)
206 + for consumer_node in lib_graph.parent_nodes(preserved_node):
207 + if consumer_node in preserved_nodes:
208 + continue
209 + providers = provider_cache.get(consumer_node)
210 + if providers is None:
211 + providers = linkmap.findProviders(consumer_node)
212 + provider_cache[consumer_node] = providers
213 + providers = providers.get(soname)
214 + if providers is None:
215 + continue
216 + for provider in providers:
217 + if provider in preserved_paths:
218 + continue
219 + provider_node = path_to_node(provider)
220 + if not provider_node.file_exists():
221 + continue
222 + if provider_node in preserved_nodes:
223 + continue
224 + # An alternative provider seems to be
225 + # installed, so drop this edge.
226 + lib_graph.remove_edge(preserved_node, consumer_node)
227 + break
228 +
229 + cpv_lib_map = {}
230 + while not lib_graph.empty():
231 + root_nodes = preserved_nodes.intersection(lib_graph.root_nodes())
232 + if not root_nodes:
233 + break
234 + lib_graph.difference_update(root_nodes)
235 + unlink_list = set()
236 + for node in root_nodes:
237 + unlink_list.update(node.alt_paths)
238 + unlink_list = sorted(unlink_list)
239 + for obj in unlink_list:
240 + cpv = path_cpv_map[obj]
241 + removed = cpv_lib_map.get(cpv)
242 + if removed is None:
243 + removed = set()
244 + cpv_lib_map[cpv] = removed
245 + removed.add(obj)
246 +
247 + return cpv_lib_map
248 +
249 + def _remove_preserved_libs(self, cpv_lib_map):
250 + """
251 + Remove files returned from _find_unused_preserved_libs().
252 + """
253 +
254 + files_to_remove = set()
255 + for files in cpv_lib_map.itervalues():
256 + files_to_remove.update(files)
257 + files_to_remove = sorted(files_to_remove)
258 + showMessage = self._display_merge
259 + root = self.myroot
260 +
261 + parent_dirs = set()
262 + for obj in files_to_remove:
263 + obj = os.path.join(root, obj.lstrip(os.sep))
264 + parent_dirs.add(os.path.dirname(obj))
265 + if os.path.islink(obj):
266 + obj_type = "sym"
267 + else:
268 + obj_type = "obj"
269 + try:
270 + os.unlink(obj)
271 + except OSError, e:
272 + if e.errno != errno.ENOENT:
273 + raise
274 + del e
275 + else:
276 + showMessage("<<< !needed %s %s\n" % (obj_type, obj))
277 +
278 + # Remove empty parent directories if possible.
279 + while parent_dirs:
280 + x = parent_dirs.pop()
281 + while True:
282 + try:
283 + os.rmdir(x)
284 + except OSError:
285 + break
286 + prev = x
287 + x = os.path.dirname(x)
288 + if x == prev:
289 + break
290 +
291 + self.vartree.dbapi.plib_registry.pruneNonExisting()
292 +
293 def _collision_protect(self, srcroot, destroot, mypkglist, mycontents):
294 collision_ignore = set([normalize_path(myignore) for myignore in \
295 shlex.split(self.settings.get("COLLISION_IGNORE", ""))])
296 @@ -3289,6 +3327,17 @@
297 contents=contents, env=self.settings.environ(),
298 writemsg_level=self._display_merge)
299
300 + # For gcc upgrades, preserved libs have to be removed after the
301 + # the library path has been updated.
302 + self.vartree.dbapi.linkmap.rebuild()
303 + cpv_lib_map = self._find_unused_preserved_libs()
304 + if cpv_lib_map:
305 + self._remove_preserved_libs(cpv_lib_map)
306 + for cpv, removed in cpv_lib_map.iteritems():
307 + if not self.vartree.dbapi.cpv_exists(cpv):
308 + continue
309 + self.vartree.dbapi.removeFromContents(cpv, removed)
310 +
311 return os.EX_OK
312
313 def mergeme(self, srcroot, destroot, outfile, secondhand, stufftomerge, cfgfiledict, thismtime):