1 |
Author: grobian |
2 |
Date: 2008-10-30 21:13:23 +0000 (Thu, 30 Oct 2008) |
3 |
New Revision: 11754 |
4 |
|
5 |
Modified: |
6 |
main/branches/prefix/bin/repoman |
7 |
main/branches/prefix/pym/_emerge/__init__.py |
8 |
main/branches/prefix/pym/portage/dbapi/vartree.py |
9 |
Log: |
10 |
Merged from trunk -r11745:11753 |
11 |
|
12 |
| 11746 | Bug #225429 - In dblink.unmerge(), eliminate consumers | |
13 |
| zmedico | having providers with the same soname as an installed | |
14 |
| | library that is not preserved. This eliminates libraries | |
15 |
| | that are erroneously preserved due to a move from one | |
16 |
| | directory to another. | |
17 |
|
18 |
| 11747 | In dblink.unmerge(), update the CONTENTS entries when | |
19 |
| zmedico | preserved libs are removed. | |
20 |
|
21 |
| 11748 | Bug # 225429 - Try to remove unneeded preserved libs just | |
22 |
| zmedico | before returning from dblink.treewalk(), after the library | |
23 |
| | path has been updated. This is intended to remove unneeded | |
24 |
| | preserved libs after a gcc upgrade. TODO: Figure out why | |
25 |
| | libgomp.so.1 still isn't properly removed. | |
26 |
|
27 |
| 11749 | Bug #225429 - Inside LinkageMap.rebuild(), update | |
28 |
| zmedico | self._defpath since it can change during a gcc upgrade. | |
29 |
|
30 |
| 11751 | define myunadded such that repoman doesn't crash when being | |
31 |
| zmedico | run in a non-{cvs,svn} dir (branches/prefix r11750) | |
32 |
|
33 |
| 11752 | Avoid unnecessary aux_get calls inside Scheduler._pkg() by | |
34 |
| zmedico | getting the existing Package instance from the digraph. | |
35 |
|
36 |
| 11753 | Make sure mychanged and mynew are always defined even if | |
37 |
| zmedico | there is no vcs because commit mode is allowed without a vcs | |
38 |
| | in pretend mode. | |
39 |
|
40 |
|
41 |
Modified: main/branches/prefix/bin/repoman |
42 |
=================================================================== |
43 |
--- main/branches/prefix/bin/repoman 2008-10-30 20:33:57 UTC (rev 11753) |
44 |
+++ main/branches/prefix/bin/repoman 2008-10-30 21:13:23 UTC (rev 11754) |
45 |
@@ -748,6 +748,8 @@ |
46 |
|
47 |
new_ebuilds = set() |
48 |
modified_changelogs = set() |
49 |
+mychanged = [] |
50 |
+mynew = [] |
51 |
if vcs == "cvs": |
52 |
mycvstree = cvstree.getentries("./", recursive=1) |
53 |
mychanged = cvstree.findchanged(mycvstree, recursive=1, basedir="./") |
54 |
|
55 |
Modified: main/branches/prefix/pym/_emerge/__init__.py |
56 |
=================================================================== |
57 |
--- main/branches/prefix/pym/_emerge/__init__.py 2008-10-30 20:33:57 UTC (rev 11753) |
58 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2008-10-30 21:13:23 UTC (rev 11754) |
59 |
@@ -10387,6 +10387,13 @@ |
60 |
if installed: |
61 |
operation = "nomerge" |
62 |
|
63 |
+ if self._digraph is not None: |
64 |
+ # Reuse existing instance when available. |
65 |
+ pkg = self._digraph.get( |
66 |
+ (type_name, root_config.root, cpv, operation)) |
67 |
+ if pkg is not None: |
68 |
+ return pkg |
69 |
+ |
70 |
tree_type = depgraph.pkg_tree_map[type_name] |
71 |
db = root_config.trees[tree_type].dbapi |
72 |
db_keys = list(self.trees[root_config.root][ |
73 |
@@ -10399,10 +10406,6 @@ |
74 |
settings.setcpv(pkg) |
75 |
pkg.metadata["USE"] = settings["PORTAGE_USE"] |
76 |
|
77 |
- if self._digraph is not None: |
78 |
- # Reuse existing instance when available. |
79 |
- pkg = self._digraph.get(pkg, pkg) |
80 |
- |
81 |
return pkg |
82 |
|
83 |
class MetadataRegen(PollScheduler): |
84 |
|
85 |
Modified: main/branches/prefix/pym/portage/dbapi/vartree.py |
86 |
=================================================================== |
87 |
--- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-10-30 20:33:57 UTC (rev 11753) |
88 |
+++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-10-30 21:13:23 UTC (rev 11754) |
89 |
@@ -220,6 +220,7 @@ |
90 |
|
91 |
def rebuild(self, exclude_pkgs=None, include_file=None): |
92 |
root = self._root |
93 |
+ self._defpath = set(getlibpaths(root)) |
94 |
libs = {} |
95 |
obj_key_cache = {} |
96 |
obj_properties = {} |
97 |
@@ -480,6 +481,11 @@ |
98 |
""" |
99 |
if not self._libs: |
100 |
self.rebuild() |
101 |
+ if isinstance(obj, self._ObjectKey): |
102 |
+ obj_key = obj |
103 |
+ if obj_key not in self._obj_properties: |
104 |
+ raise KeyError("%s not in object list" % obj_key) |
105 |
+ return self._obj_properties[obj_key][3] |
106 |
if obj not in self._obj_key_cache: |
107 |
raise KeyError("%s not in object list" % obj) |
108 |
return self._obj_properties[self._obj_key_cache[obj]][3] |
109 |
@@ -930,6 +936,11 @@ |
110 |
""" |
111 |
if not self._libs: |
112 |
self.rebuild() |
113 |
+ if isinstance(obj, self._ObjectKey): |
114 |
+ obj_key = obj |
115 |
+ if obj_key not in self._obj_properties: |
116 |
+ raise KeyError("%s not in object list" % obj_key) |
117 |
+ return self._obj_properties[obj_key][2] |
118 |
if obj not in self._obj_key_cache: |
119 |
raise KeyError("%s not in object list" % obj) |
120 |
return self._obj_properties[self._obj_key_cache[obj]][2] |
121 |
@@ -2393,61 +2404,21 @@ |
122 |
self.vartree.dbapi.linkmap.rebuild(exclude_pkgs=(self.mycpv,)) |
123 |
|
124 |
# remove preserved libraries that don't have any consumers left |
125 |
- # Since preserved libraries can be consumers of other preserved |
126 |
- # libraries, use a graph to track consumer relationships. |
127 |
- plib_dict = plib_registry.getPreservedLibs() |
128 |
- lib_graph = digraph() |
129 |
- preserved_nodes = set() |
130 |
- root = self.myroot |
131 |
- for plibs in plib_dict.itervalues(): |
132 |
- for f in plibs: |
133 |
- preserved_node = LinkageMap._LibGraphNode(f, root) |
134 |
- if not preserved_node.file_exists(): |
135 |
+ cpv_lib_map = self._find_unused_preserved_libs() |
136 |
+ if cpv_lib_map: |
137 |
+ self._remove_preserved_libs(cpv_lib_map) |
138 |
+ for cpv, removed in cpv_lib_map.iteritems(): |
139 |
+ if not self.vartree.dbapi.cpv_exists(cpv): |
140 |
+ for dblnk in others_in_slot: |
141 |
+ if dblnk.mycpv == cpv: |
142 |
+ # This one just got merged so it doesn't |
143 |
+ # register with cpv_exists() yet. |
144 |
+ self.vartree.dbapi.removeFromContents( |
145 |
+ dblnk, removed) |
146 |
+ break |
147 |
continue |
148 |
- existing_node = lib_graph.get(preserved_node) |
149 |
- if existing_node is not None: |
150 |
- preserved_node = existing_node |
151 |
- else: |
152 |
- lib_graph.add(preserved_node, None) |
153 |
- preserved_node.alt_paths.add(f) |
154 |
- preserved_nodes.add(preserved_node) |
155 |
- for c in self.vartree.dbapi.linkmap.findConsumers(f): |
156 |
- consumer_node = LinkageMap._LibGraphNode(c, root) |
157 |
- if not consumer_node.file_exists(): |
158 |
- continue |
159 |
- # Note that consumers may also be providers. |
160 |
- existing_node = lib_graph.get(consumer_node) |
161 |
- if existing_node is not None: |
162 |
- consumer_node = existing_node |
163 |
- consumer_node.alt_paths.add(c) |
164 |
- lib_graph.add(preserved_node, consumer_node) |
165 |
+ self.vartree.dbapi.removeFromContents(cpv, removed) |
166 |
|
167 |
- while not lib_graph.empty(): |
168 |
- root_nodes = preserved_nodes.intersection(lib_graph.root_nodes()) |
169 |
- if not root_nodes: |
170 |
- break |
171 |
- lib_graph.difference_update(root_nodes) |
172 |
- unlink_list = set() |
173 |
- for node in root_nodes: |
174 |
- unlink_list.update(node.alt_paths) |
175 |
- unlink_list = sorted(unlink_list) |
176 |
- for obj in unlink_list: |
177 |
- obj = os.path.join(root, obj.lstrip(os.sep)) |
178 |
- if os.path.islink(obj): |
179 |
- obj_type = "sym" |
180 |
- else: |
181 |
- obj_type = "obj" |
182 |
- try: |
183 |
- os.unlink(obj) |
184 |
- except OSError, e: |
185 |
- if e.errno != errno.ENOENT: |
186 |
- raise |
187 |
- del e |
188 |
- else: |
189 |
- showMessage("<<< !needed %s %s\n" % (obj_type, obj)) |
190 |
- |
191 |
- plib_registry.pruneNonExisting() |
192 |
- |
193 |
finally: |
194 |
if builddir_lock: |
195 |
try: |
196 |
@@ -3023,8 +2994,143 @@ |
197 |
# keep track of the libs we preserved |
198 |
self.vartree.dbapi.plib_registry.register(self.mycpv, self.settings["SLOT"], counter, preserve_paths) |
199 |
|
200 |
- del preserve_paths |
201 |
- |
202 |
+ def _find_unused_preserved_libs(self): |
203 |
+ """ |
204 |
+ Find preserved libraries that don't have any consumers left. |
205 |
+ """ |
206 |
+ |
207 |
+ # Since preserved libraries can be consumers of other preserved |
208 |
+ # libraries, use a graph to track consumer relationships. |
209 |
+ plib_dict = self.vartree.dbapi.plib_registry.getPreservedLibs() |
210 |
+ lib_graph = digraph() |
211 |
+ preserved_nodes = set() |
212 |
+ preserved_paths = set() |
213 |
+ path_cpv_map = {} |
214 |
+ path_node_map = {} |
215 |
+ root = self.myroot |
216 |
+ |
217 |
+ def path_to_node(path): |
218 |
+ node = path_node_map.get(path) |
219 |
+ if node is None: |
220 |
+ node = LinkageMap._LibGraphNode(path, root) |
221 |
+ alt_path_node = lib_graph.get(node) |
222 |
+ if alt_path_node is not None: |
223 |
+ node = alt_path_node |
224 |
+ node.alt_paths.add(path) |
225 |
+ path_node_map[path] = node |
226 |
+ return node |
227 |
+ |
228 |
+ linkmap = self.vartree.dbapi.linkmap |
229 |
+ for cpv, plibs in plib_dict.iteritems(): |
230 |
+ for f in plibs: |
231 |
+ path_cpv_map[f] = cpv |
232 |
+ preserved_node = path_to_node(f) |
233 |
+ if not preserved_node.file_exists(): |
234 |
+ continue |
235 |
+ lib_graph.add(preserved_node, None) |
236 |
+ preserved_paths.add(f) |
237 |
+ preserved_nodes.add(preserved_node) |
238 |
+ for c in self.vartree.dbapi.linkmap.findConsumers(f): |
239 |
+ consumer_node = path_to_node(c) |
240 |
+ if not consumer_node.file_exists(): |
241 |
+ continue |
242 |
+ # Note that consumers may also be providers. |
243 |
+ lib_graph.add(preserved_node, consumer_node) |
244 |
+ |
245 |
+ # Eliminate consumers having providers with the same soname as an |
246 |
+ # installed library that is not preserved. This eliminates |
247 |
+ # libraries that are erroneously preserved due to a move from one |
248 |
+ # directory to another. |
249 |
+ provider_cache = {} |
250 |
+ for preserved_node in preserved_nodes: |
251 |
+ soname = linkmap.getSoname(preserved_node) |
252 |
+ for consumer_node in lib_graph.parent_nodes(preserved_node): |
253 |
+ if consumer_node in preserved_nodes: |
254 |
+ continue |
255 |
+ providers = provider_cache.get(consumer_node) |
256 |
+ if providers is None: |
257 |
+ providers = linkmap.findProviders(consumer_node) |
258 |
+ provider_cache[consumer_node] = providers |
259 |
+ providers = providers.get(soname) |
260 |
+ if providers is None: |
261 |
+ continue |
262 |
+ for provider in providers: |
263 |
+ if provider in preserved_paths: |
264 |
+ continue |
265 |
+ provider_node = path_to_node(provider) |
266 |
+ if not provider_node.file_exists(): |
267 |
+ continue |
268 |
+ if provider_node in preserved_nodes: |
269 |
+ continue |
270 |
+ # An alternative provider seems to be |
271 |
+ # installed, so drop this edge. |
272 |
+ lib_graph.remove_edge(preserved_node, consumer_node) |
273 |
+ break |
274 |
+ |
275 |
+ cpv_lib_map = {} |
276 |
+ while not lib_graph.empty(): |
277 |
+ root_nodes = preserved_nodes.intersection(lib_graph.root_nodes()) |
278 |
+ if not root_nodes: |
279 |
+ break |
280 |
+ lib_graph.difference_update(root_nodes) |
281 |
+ unlink_list = set() |
282 |
+ for node in root_nodes: |
283 |
+ unlink_list.update(node.alt_paths) |
284 |
+ unlink_list = sorted(unlink_list) |
285 |
+ for obj in unlink_list: |
286 |
+ cpv = path_cpv_map[obj] |
287 |
+ removed = cpv_lib_map.get(cpv) |
288 |
+ if removed is None: |
289 |
+ removed = set() |
290 |
+ cpv_lib_map[cpv] = removed |
291 |
+ removed.add(obj) |
292 |
+ |
293 |
+ return cpv_lib_map |
294 |
+ |
295 |
+ def _remove_preserved_libs(self, cpv_lib_map): |
296 |
+ """ |
297 |
+ Remove files returned from _find_unused_preserved_libs(). |
298 |
+ """ |
299 |
+ |
300 |
+ files_to_remove = set() |
301 |
+ for files in cpv_lib_map.itervalues(): |
302 |
+ files_to_remove.update(files) |
303 |
+ files_to_remove = sorted(files_to_remove) |
304 |
+ showMessage = self._display_merge |
305 |
+ root = self.myroot |
306 |
+ |
307 |
+ parent_dirs = set() |
308 |
+ for obj in files_to_remove: |
309 |
+ obj = os.path.join(root, obj.lstrip(os.sep)) |
310 |
+ parent_dirs.add(os.path.dirname(obj)) |
311 |
+ if os.path.islink(obj): |
312 |
+ obj_type = "sym" |
313 |
+ else: |
314 |
+ obj_type = "obj" |
315 |
+ try: |
316 |
+ os.unlink(obj) |
317 |
+ except OSError, e: |
318 |
+ if e.errno != errno.ENOENT: |
319 |
+ raise |
320 |
+ del e |
321 |
+ else: |
322 |
+ showMessage("<<< !needed %s %s\n" % (obj_type, obj)) |
323 |
+ |
324 |
+ # Remove empty parent directories if possible. |
325 |
+ while parent_dirs: |
326 |
+ x = parent_dirs.pop() |
327 |
+ while True: |
328 |
+ try: |
329 |
+ os.rmdir(x) |
330 |
+ except OSError: |
331 |
+ break |
332 |
+ prev = x |
333 |
+ x = os.path.dirname(x) |
334 |
+ if x == prev: |
335 |
+ break |
336 |
+ |
337 |
+ self.vartree.dbapi.plib_registry.pruneNonExisting() |
338 |
+ |
339 |
def _collision_protect(self, srcroot, destroot, mypkglist, mycontents): |
340 |
collision_ignore = set([normalize_path(myignore) for myignore in \ |
341 |
shlex.split(self.settings.get("COLLISION_IGNORE", ""))]) |
342 |
@@ -3680,6 +3786,17 @@ |
343 |
contents=contents, env=self.settings.environ(), |
344 |
writemsg_level=self._display_merge) |
345 |
|
346 |
+ # For gcc upgrades, preserved libs have to be removed after the |
347 |
+ # the library path has been updated. |
348 |
+ self.vartree.dbapi.linkmap.rebuild() |
349 |
+ cpv_lib_map = self._find_unused_preserved_libs() |
350 |
+ if cpv_lib_map: |
351 |
+ self._remove_preserved_libs(cpv_lib_map) |
352 |
+ for cpv, removed in cpv_lib_map.iteritems(): |
353 |
+ if not self.vartree.dbapi.cpv_exists(cpv): |
354 |
+ continue |
355 |
+ self.vartree.dbapi.removeFromContents(cpv, removed) |
356 |
+ |
357 |
return os.EX_OK |
358 |
|
359 |
def mergeme(self, srcroot, destroot, outfile, secondhand, stufftomerge, cfgfiledict, thismtime): |