1 |
commit: abd5adceac4b5f95de66be7516d4f29f24f00d02 |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri May 27 17:39:37 2011 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri May 27 17:39:37 2011 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=abd5adce |
7 |
|
8 |
Merge remote-tracking branch 'overlays-gentoo-org/master' into prefix |
9 |
|
10 |
Ported changes to LinkageMapELF to the other LinkageMaps |
11 |
|
12 |
Conflicts: |
13 |
bin/etc-update |
14 |
bin/glsa-check |
15 |
bin/regenworld |
16 |
pym/portage/dbapi/vartree.py |
17 |
|
18 |
|
19 |
bin/ebuild.sh | 7 + |
20 |
bin/etc-update | 8 +- |
21 |
bin/glsa-check | 4 +- |
22 |
bin/regenworld | 6 +- |
23 |
bin/repoman | 2 +- |
24 |
cnf/make.conf.sparc.diff | 2 +- |
25 |
doc/package/ebuild/eapi/4.docbook | 4 +- |
26 |
make.conf.txt | 719 -------------------- |
27 |
man/ebuild.5 | 4 +- |
28 |
man/emerge.1 | 15 +- |
29 |
man/make.conf.5 | 5 +- |
30 |
pym/_emerge/AsynchronousLock.py | 49 ++- |
31 |
pym/_emerge/AsynchronousTask.py | 5 +- |
32 |
pym/_emerge/Binpkg.py | 3 +- |
33 |
pym/_emerge/BinpkgFetcher.py | 7 +- |
34 |
pym/_emerge/Blocker.py | 12 +- |
35 |
pym/_emerge/BlockerDB.py | 9 +- |
36 |
pym/_emerge/DepPriority.py | 2 +- |
37 |
pym/_emerge/DepPrioritySatisfiedRange.py | 31 +- |
38 |
pym/_emerge/EbuildBuild.py | 3 +- |
39 |
pym/_emerge/EbuildBuildDir.py | 29 +- |
40 |
pym/_emerge/EbuildMerge.py | 23 +- |
41 |
pym/_emerge/EbuildPhase.py | 34 +- |
42 |
pym/_emerge/FakeVartree.py | 21 +- |
43 |
pym/_emerge/Package.py | 59 ++- |
44 |
pym/_emerge/PackageUninstall.py | 102 +++- |
45 |
pym/_emerge/Scheduler.py | 24 +- |
46 |
pym/_emerge/Task.py | 31 +- |
47 |
pym/_emerge/actions.py | 30 +- |
48 |
pym/_emerge/depgraph.py | 617 ++++++++++++++---- |
49 |
pym/_emerge/help.py | 16 +- |
50 |
pym/_emerge/main.py | 17 +- |
51 |
pym/_emerge/resolver/backtracking.py | 7 +- |
52 |
pym/_emerge/resolver/output_helpers.py | 4 +- |
53 |
pym/_emerge/unmerge.py | 74 ++- |
54 |
pym/portage/const.py | 2 +- |
55 |
pym/portage/cvstree.py | 6 +- |
56 |
pym/portage/dbapi/_MergeProcess.py | 43 +- |
57 |
pym/portage/dbapi/vartree.py | 315 ++++++--- |
58 |
pym/portage/mail.py | 11 +- |
59 |
pym/portage/output.py | 4 +- |
60 |
pym/portage/package/ebuild/doebuild.py | 121 ++-- |
61 |
pym/portage/package/ebuild/getmaskingstatus.py | 7 +- |
62 |
pym/portage/tests/ebuild/test_config.py | 4 +- |
63 |
pym/portage/tests/locks/test_asynchronous_lock.py | 95 +++- |
64 |
pym/portage/tests/resolver/ResolverPlayground.py | 99 +++- |
65 |
pym/portage/tests/resolver/test_autounmask.py | 51 ++- |
66 |
.../tests/resolver/test_circular_dependencies.py | 3 +- |
67 |
pym/portage/tests/resolver/test_depth.py | 8 +- |
68 |
pym/portage/tests/resolver/test_merge_order.py | 386 +++++++++++ |
69 |
pym/portage/tests/resolver/test_multirepo.py | 3 + |
70 |
.../tests/resolver/test_old_dep_chain_display.py | 2 + |
71 |
pym/portage/tests/resolver/test_simple.py | 2 +- |
72 |
pym/portage/tests/resolver/test_slot_collisions.py | 3 +- |
73 |
pym/portage/update.py | 4 +- |
74 |
pym/portage/util/__init__.py | 29 +- |
75 |
pym/portage/util/_dyn_libs/LinkageMapELF.py | 13 +- |
76 |
pym/portage/util/_dyn_libs/LinkageMapMachO.py | 13 +- |
77 |
pym/portage/util/_dyn_libs/LinkageMapPeCoff.py | 11 +- |
78 |
pym/portage/util/_dyn_libs/LinkageMapXCoff.py | 11 +- |
79 |
pym/portage/util/digraph.py | 10 +- |
80 |
pym/portage/util/movefile.py | 5 +- |
81 |
pym/portage/xml/metadata.py | 4 +- |
82 |
63 files changed, 1948 insertions(+), 1302 deletions(-) |
83 |
|
84 |
diff --cc bin/etc-update |
85 |
index 5fbd345,2369f04..2054389 |
86 |
--- a/bin/etc-update |
87 |
+++ b/bin/etc-update |
88 |
@@@ -1,5 -1,5 +1,5 @@@ |
89 |
-#!/bin/bash |
90 |
+#!@PORTAGE_BASH@ |
91 |
- # Copyright 1999-2007 Gentoo Foundation |
92 |
+ # Copyright 1999-2011 Gentoo Foundation |
93 |
# Distributed under the terms of the GNU General Public License v2 |
94 |
|
95 |
# Author Brandon Low <lostlogic@g.o> |
96 |
diff --cc bin/glsa-check |
97 |
index 64209ab,2f2d555..4f50a1f |
98 |
--- a/bin/glsa-check |
99 |
+++ b/bin/glsa-check |
100 |
@@@ -1,5 -1,5 +1,5 @@@ |
101 |
-#!/usr/bin/python |
102 |
+#!@PREFIX_PORTAGE_PYTHON@ |
103 |
- # Copyright 2008-2009 Gentoo Foundation |
104 |
+ # Copyright 2008-2011 Gentoo Foundation |
105 |
# Distributed under the terms of the GNU General Public License v2 |
106 |
|
107 |
from __future__ import print_function |
108 |
diff --cc bin/regenworld |
109 |
index e0e9774,6b5af4c..9e0e291 |
110 |
--- a/bin/regenworld |
111 |
+++ b/bin/regenworld |
112 |
@@@ -1,5 -1,5 +1,5 @@@ |
113 |
-#!/usr/bin/python |
114 |
+#!@PREFIX_PORTAGE_PYTHON@ |
115 |
- # Copyright 1999-2010 Gentoo Foundation |
116 |
+ # Copyright 1999-2011 Gentoo Foundation |
117 |
# Distributed under the terms of the GNU General Public License v2 |
118 |
|
119 |
from __future__ import print_function |
120 |
diff --cc pym/portage/const.py |
121 |
index 6057520,e91c009..00a53e4 |
122 |
--- a/pym/portage/const.py |
123 |
+++ b/pym/portage/const.py |
124 |
@@@ -132,10 -88,9 +132,10 @@@ EBUILD_PHASES = ("pretend", |
125 |
SUPPORTED_FEATURES = frozenset([ |
126 |
"assume-digests", "binpkg-logs", "buildpkg", "buildsyspkg", "candy", |
127 |
"ccache", "chflags", "collision-protect", "compress-build-logs", |
128 |
- "digest", "distcc", "distlocks", "ebuild-locks", "fakeroot", |
129 |
+ "digest", "distcc", "distcc-pump", "distlocks", "ebuild-locks", "fakeroot", |
130 |
"fail-clean", "fixpackages", "force-mirror", "getbinpkg", |
131 |
"installsources", "keeptemp", "keepwork", "fixlafiles", "lmirror", |
132 |
+ "macossandbox", "macosprefixsandbox", "macosusersandbox", |
133 |
"metadata-transfer", "mirror", "multilib-strict", "news", |
134 |
"noauto", "noclean", "nodoc", "noinfo", "noman", |
135 |
"nostrip", "notitles", "parallel-fetch", "parallel-install", |
136 |
diff --cc pym/portage/dbapi/vartree.py |
137 |
index 581300f,e742358..e0f0856 |
138 |
--- a/pym/portage/dbapi/vartree.py |
139 |
+++ b/pym/portage/dbapi/vartree.py |
140 |
@@@ -2347,7 -2386,7 +2407,7 @@@ class dblink(object) |
141 |
def path_to_node(path): |
142 |
node = path_node_map.get(path) |
143 |
if node is None: |
144 |
- node = linkmap._LibGraphNode(path, root) |
145 |
- node = LinkageMap._LibGraphNode(linkmap._obj_key(path)) |
146 |
++ node = linkmap._LibGraphNode(linkmap._obj_key(path)) |
147 |
alt_path_node = lib_graph.get(node) |
148 |
if alt_path_node is not None: |
149 |
node = alt_path_node |
150 |
@@@ -2512,15 -2552,7 +2573,15 @@@ |
151 |
def path_to_node(path): |
152 |
node = path_node_map.get(path) |
153 |
if node is None: |
154 |
- node = LinkageMap._LibGraphNode(linkmap._obj_key(path)) |
155 |
+ chost = self.settings.get('CHOST') |
156 |
+ if chost.find('darwin') >= 0: |
157 |
- node = LinkageMapMachO._LibGraphNode(path, root) |
158 |
++ node = LinkageMapMachO._LibGraphNode(linkmap._obj_key(path)) |
159 |
+ elif chost.find('interix') >= 0 or chost.find('winnt') >= 0: |
160 |
- node = LinkageMapPeCoff._LibGraphNode(path, root) |
161 |
++ node = LinkageMapPeCoff._LibGraphNode(linkmap._obj_key(path)) |
162 |
+ elif chost.find('aix') >= 0: |
163 |
- node = LinkageMapXCoff._LibGraphNode(path, root) |
164 |
++ node = LinkageMapXCoff._LibGraphNode(linkmap._obj_key(path)) |
165 |
+ else: |
166 |
- node = LinkageMap._LibGraphNode(path, root) |
167 |
++ node = LinkageMap._LibGraphNode(linkmap._obj_key(path)) |
168 |
alt_path_node = lib_graph.get(node) |
169 |
if alt_path_node is not None: |
170 |
node = alt_path_node |
171 |
diff --cc pym/portage/util/_dyn_libs/LinkageMapMachO.py |
172 |
index cbdf6c2,fef75b6..7ed004a |
173 |
--- a/pym/portage/util/_dyn_libs/LinkageMapMachO.py |
174 |
+++ b/pym/portage/util/_dyn_libs/LinkageMapMachO.py |
175 |
@@@ -59,7 -60,7 +59,7 @@@ class LinkageMapMachO(object) |
176 |
|
177 |
"""Helper class used as _obj_properties keys for objects.""" |
178 |
|
179 |
- __slots__ = ("__weakref__", "_key") |
180 |
- __slots__ = ("_key",) |
181 |
++ __slots__ = ("_key") |
182 |
|
183 |
def __init__(self, obj, root): |
184 |
""" |
185 |
diff --cc pym/portage/util/_dyn_libs/LinkageMapPeCoff.py |
186 |
index c90947e,0000000..25e8a45 |
187 |
mode 100644,000000..100644 |
188 |
--- a/pym/portage/util/_dyn_libs/LinkageMapPeCoff.py |
189 |
+++ b/pym/portage/util/_dyn_libs/LinkageMapPeCoff.py |
190 |
@@@ -1,267 -1,0 +1,274 @@@ |
191 |
+# Copyright 1998-2011 Gentoo Foundation |
192 |
+# Distributed under the terms of the GNU General Public License v2 |
193 |
+ |
194 |
+import errno |
195 |
+import logging |
196 |
+import subprocess |
197 |
+ |
198 |
+import portage |
199 |
+from portage import _encodings |
200 |
+from portage import _os_merge |
201 |
+from portage import _unicode_decode |
202 |
+from portage import _unicode_encode |
203 |
+from portage.cache.mappings import slot_dict_class |
204 |
+from portage.exception import CommandNotFound |
205 |
+from portage.localization import _ |
206 |
+from portage.util import getlibpaths |
207 |
+from portage.util import grabfile |
208 |
+from portage.util import normalize_path |
209 |
+from portage.util import writemsg_level |
210 |
+from portage.const import EPREFIX |
211 |
+from portage.util._dyn_libs.LinkageMapELF import LinkageMapELF |
212 |
+ |
213 |
+class LinkageMapPeCoff(LinkageMapELF): |
214 |
+ |
215 |
+ """Models dynamic linker dependencies.""" |
216 |
+ |
217 |
+ # NEEDED.PECOFF.1 has effectively the _same_ format as NEEDED.ELF.2, |
218 |
+ # but we keep up the relation "scanelf" -> "NEEDED.ELF", "readpecoff" -> |
219 |
+ # "NEEDED.PECOFF", "scanmacho" -> "NEEDED.MACHO", etc. others will follow. |
220 |
+ _needed_aux_key = "NEEDED.PECOFF.1" |
221 |
+ |
222 |
+ class _ObjectKey(LinkageMapELF._ObjectKey): |
223 |
+ |
224 |
+ """Helper class used as _obj_properties keys for objects.""" |
225 |
+ |
226 |
+ def _generate_object_key(self, obj, root): |
227 |
+ """ |
228 |
+ Generate object key for a given object. This is different from the |
229 |
+ Linux implementation, since some systems (e.g. interix) don't have |
230 |
+ "inodes", thus the inode field is always zero, or a random value, |
231 |
+ making it inappropriate for identifying a file... :) |
232 |
+ |
233 |
+ @param object: path to a file |
234 |
+ @type object: string (example: '/usr/bin/bar') |
235 |
+ @rtype: 2-tuple of types (bool, string) |
236 |
+ @return: |
237 |
+ 2-tuple of boolean indicating existance, and absolut path |
238 |
+ """ |
239 |
+ |
240 |
+ os = _os_merge |
241 |
+ |
242 |
+ try: |
243 |
+ _unicode_encode(obj, |
244 |
+ encoding=_encodings['merge'], errors='strict') |
245 |
+ except UnicodeEncodeError: |
246 |
+ # The package appears to have been merged with a |
247 |
+ # different value of sys.getfilesystemencoding(), |
248 |
+ # so fall back to utf_8 if appropriate. |
249 |
+ try: |
250 |
+ _unicode_encode(obj, |
251 |
+ encoding=_encodings['fs'], errors='strict') |
252 |
+ except UnicodeEncodeError: |
253 |
+ pass |
254 |
+ else: |
255 |
+ os = portage.os |
256 |
+ |
257 |
+ abs_path = os.path.join(root, obj.lstrip(os.sep)) |
258 |
+ try: |
259 |
+ object_stat = os.stat(abs_path) |
260 |
+ except OSError: |
261 |
+ return (False, os.path.realpath(abs_path)) |
262 |
+ # On Interix, the inode field may always be zero, since the |
263 |
+ # filesystem (NTFS) has no inodes ... |
264 |
+ return (True, os.path.realpath(abs_path)) |
265 |
+ |
266 |
+ def file_exists(self): |
267 |
+ """ |
268 |
+ Determine if the file for this key exists on the filesystem. |
269 |
+ |
270 |
+ @rtype: Boolean |
271 |
+ @return: |
272 |
+ 1. True if the file exists. |
273 |
+ 2. False if the file does not exist or is a broken symlink. |
274 |
+ |
275 |
+ """ |
276 |
+ return self._key[0] |
277 |
+ |
278 |
+ class _LibGraphNode(_ObjectKey): |
279 |
+ __slots__ = ("alt_paths",) |
280 |
+ |
281 |
- def __init__(self, obj, root): |
282 |
- LinkageMapPeCoff._ObjectKey.__init__(self, obj, root) |
283 |
++ def __init__(self, key): |
284 |
++ """ |
285 |
++ Create a _LibGraphNode from an existing _ObjectKey. |
286 |
++ This re-uses the _key attribute in order to avoid repeating |
287 |
++ any previous stat calls, which helps to avoid potential race |
288 |
++ conditions due to inconsistent stat results when the |
289 |
++ file system is being modified concurrently. |
290 |
++ """ |
291 |
++ self._key = key._key |
292 |
+ self.alt_paths = set() |
293 |
+ |
294 |
+ def __str__(self): |
295 |
+ return str(sorted(self.alt_paths)) |
296 |
+ |
297 |
+ def rebuild(self, exclude_pkgs=None, include_file=None, |
298 |
+ preserve_paths=None): |
299 |
+ """ |
300 |
+ Raises CommandNotFound if there are preserved libs |
301 |
+ and the readpecoff binary is not available. |
302 |
+ |
303 |
+ @param exclude_pkgs: A set of packages that should be excluded from |
304 |
+ the LinkageMap, since they are being unmerged and their NEEDED |
305 |
+ entries are therefore irrelevant and would only serve to corrupt |
306 |
+ the LinkageMap. |
307 |
+ @type exclude_pkgs: set |
308 |
+ @param include_file: The path of a file containing NEEDED entries for |
309 |
+ a package which does not exist in the vardbapi yet because it is |
310 |
+ currently being merged. |
311 |
+ @type include_file: String |
312 |
+ @param preserve_paths: Libraries preserved by a package instance that |
313 |
+ is currently being merged. They need to be explicitly passed to the |
314 |
+ LinkageMap, since they are not registered in the |
315 |
+ PreservedLibsRegistry yet. |
316 |
+ @type preserve_paths: set |
317 |
+ """ |
318 |
+ |
319 |
+ os = _os_merge |
320 |
+ root = self._root |
321 |
+ root_len = len(root) - 1 |
322 |
+ self._clear_cache() |
323 |
+ self._defpath.update(getlibpaths(self._root)) |
324 |
+ libs = self._libs |
325 |
+ obj_properties = self._obj_properties |
326 |
+ |
327 |
+ lines = [] |
328 |
+ |
329 |
+ # Data from include_file is processed first so that it |
330 |
+ # overrides any data from previously installed files. |
331 |
+ if include_file is not None: |
332 |
+ for line in grabfile(include_file): |
333 |
+ lines.append((include_file, line)) |
334 |
+ |
335 |
+ aux_keys = [self._needed_aux_key] |
336 |
+ can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK) |
337 |
+ if can_lock: |
338 |
+ self._dbapi.lock() |
339 |
+ try: |
340 |
+ for cpv in self._dbapi.cpv_all(): |
341 |
+ if exclude_pkgs is not None and cpv in exclude_pkgs: |
342 |
+ continue |
343 |
+ needed_file = self._dbapi.getpath(cpv, |
344 |
+ filename=self._needed_aux_key) |
345 |
+ for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines(): |
346 |
+ lines.append((needed_file, line)) |
347 |
+ finally: |
348 |
+ if can_lock: |
349 |
+ self._dbapi.unlock() |
350 |
+ |
351 |
+ # have to call readpecoff for preserved libs here as they aren't |
352 |
+ # registered in NEEDED.PECOFF.1 files |
353 |
+ plibs = set() |
354 |
+ if preserve_paths is not None: |
355 |
+ plibs.update(preserve_paths) |
356 |
+ if self._dbapi._plib_registry and \ |
357 |
+ self._dbapi._plib_registry.hasEntries(): |
358 |
+ for cpv, items in \ |
359 |
+ self._dbapi._plib_registry.getPreservedLibs().items(): |
360 |
+ if exclude_pkgs is not None and cpv in exclude_pkgs: |
361 |
+ # These preserved libs will either be unmerged, |
362 |
+ # rendering them irrelevant, or they will be |
363 |
+ # preserved in the replacement package and are |
364 |
+ # already represented via the preserve_paths |
365 |
+ # parameter. |
366 |
+ continue |
367 |
+ plibs.update(items) |
368 |
+ if plibs: |
369 |
+ args = ["readpecoff", self._dbapi.settings.get('CHOST')] |
370 |
+ args.extend(os.path.join(root, x.lstrip("." + os.sep)) \ |
371 |
+ for x in plibs) |
372 |
+ try: |
373 |
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE) |
374 |
+ except EnvironmentError as e: |
375 |
+ if e.errno != errno.ENOENT: |
376 |
+ raise |
377 |
+ raise CommandNotFound(args[0]) |
378 |
+ else: |
379 |
+ for l in proc.stdout: |
380 |
+ try: |
381 |
+ l = _unicode_decode(l, |
382 |
+ encoding=_encodings['content'], errors='strict') |
383 |
+ except UnicodeDecodeError: |
384 |
+ l = _unicode_decode(l, |
385 |
+ encoding=_encodings['content'], errors='replace') |
386 |
+ writemsg_level(_("\nError decoding characters " \ |
387 |
+ "returned from readpecoff: %s\n\n") % (l,), |
388 |
+ level=logging.ERROR, noiselevel=-1) |
389 |
+ l = l[3:].rstrip("\n") |
390 |
+ if not l: |
391 |
+ continue |
392 |
+ fields = l.split(";") |
393 |
+ if len(fields) < 5: |
394 |
+ writemsg_level(_("\nWrong number of fields " \ |
395 |
+ "returned from readpecoff: %s\n\n") % (l,), |
396 |
+ level=logging.ERROR, noiselevel=-1) |
397 |
+ continue |
398 |
+ fields[1] = fields[1][root_len:] |
399 |
+ plibs.discard(fields[1]) |
400 |
+ lines.append(("readpecoff", ";".join(fields))) |
401 |
+ proc.wait() |
402 |
+ |
403 |
+ if plibs: |
404 |
+ # Preserved libraries that did not appear in the scanelf output. |
405 |
+ # This is known to happen with statically linked libraries. |
406 |
+ # Generate dummy lines for these, so we can assume that every |
407 |
+ # preserved library has an entry in self._obj_properties. This |
408 |
+ # is important in order to prevent findConsumers from raising |
409 |
+ # an unwanted KeyError. |
410 |
+ for x in plibs: |
411 |
+ lines.append(("plibs", ";".join(['', x, '', '', '']))) |
412 |
+ |
413 |
+ for location, l in lines: |
414 |
+ l = l.rstrip("\n") |
415 |
+ if not l: |
416 |
+ continue |
417 |
+ fields = l.split(";") |
418 |
+ if len(fields) < 5: |
419 |
+ writemsg_level(_("\nWrong number of fields " \ |
420 |
+ "in %s: %s\n\n") % (location, l), |
421 |
+ level=logging.ERROR, noiselevel=-1) |
422 |
+ continue |
423 |
+ arch = fields[0] |
424 |
+ obj = fields[1] |
425 |
+ soname = fields[2] |
426 |
+ path = set([normalize_path(x) \ |
427 |
+ for x in filter(None, fields[3].replace( |
428 |
+ "${ORIGIN}", os.path.dirname(obj)).replace( |
429 |
+ "$ORIGIN", os.path.dirname(obj)).split(":"))]) |
430 |
+ needed = [x for x in fields[4].split(",") if x] |
431 |
+ |
432 |
+ obj_key = self._obj_key(obj) |
433 |
+ indexed = True |
434 |
+ myprops = obj_properties.get(obj_key) |
435 |
+ if myprops is None: |
436 |
+ indexed = False |
437 |
+ myprops = (arch, needed, path, soname, set()) |
438 |
+ obj_properties[obj_key] = myprops |
439 |
+ # All object paths are added into the obj_properties tuple. |
440 |
+ myprops[4].add(obj) |
441 |
+ |
442 |
+ # Don't index the same file more that once since only one |
443 |
+ # set of data can be correct and therefore mixing data |
444 |
+ # may corrupt the index (include_file overrides previously |
445 |
+ # installed). |
446 |
+ if indexed: |
447 |
+ continue |
448 |
+ |
449 |
+ arch_map = libs.get(arch) |
450 |
+ if arch_map is None: |
451 |
+ arch_map = {} |
452 |
+ libs[arch] = arch_map |
453 |
+ if soname: |
454 |
+ soname_map = arch_map.get(soname) |
455 |
+ if soname_map is None: |
456 |
+ soname_map = self._soname_map_class( |
457 |
+ providers=set(), consumers=set()) |
458 |
+ arch_map[soname] = soname_map |
459 |
+ soname_map.providers.add(obj_key) |
460 |
+ for needed_soname in needed: |
461 |
+ soname_map = arch_map.get(needed_soname) |
462 |
+ if soname_map is None: |
463 |
+ soname_map = self._soname_map_class( |
464 |
+ providers=set(), consumers=set()) |
465 |
+ arch_map[needed_soname] = soname_map |
466 |
+ soname_map.consumers.add(obj_key) |
467 |
diff --cc pym/portage/util/_dyn_libs/LinkageMapXCoff.py |
468 |
index 0e930fe,0000000..782cc54 |
469 |
mode 100644,000000..100644 |
470 |
--- a/pym/portage/util/_dyn_libs/LinkageMapXCoff.py |
471 |
+++ b/pym/portage/util/_dyn_libs/LinkageMapXCoff.py |
472 |
@@@ -1,319 -1,0 +1,326 @@@ |
473 |
+# Copyright 1998-2011 Gentoo Foundation |
474 |
+# Distributed under the terms of the GNU General Public License v2 |
475 |
+ |
476 |
+import errno |
477 |
+import logging |
478 |
+import subprocess |
479 |
+ |
480 |
+import portage |
481 |
+from portage import _encodings |
482 |
+from portage import _os_merge |
483 |
+from portage import _unicode_decode |
484 |
+from portage import _unicode_encode |
485 |
+from portage.cache.mappings import slot_dict_class |
486 |
+from portage.exception import CommandNotFound |
487 |
+from portage.localization import _ |
488 |
+from portage.util import getlibpaths |
489 |
+from portage.util import grabfile |
490 |
+from portage.util import normalize_path |
491 |
+from portage.util import writemsg_level |
492 |
+from portage.const import EPREFIX, BASH_BINARY |
493 |
+from portage.util._dyn_libs.LinkageMapELF import LinkageMapELF |
494 |
+ |
495 |
+class LinkageMapXCoff(LinkageMapELF): |
496 |
+ |
497 |
+ """Models dynamic linker dependencies.""" |
498 |
+ |
499 |
+ _needed_aux_key = "NEEDED.XCOFF.1" |
500 |
+ |
501 |
+ class _ObjectKey(LinkageMapELF._ObjectKey): |
502 |
+ |
503 |
+ def __init__(self, obj, root): |
504 |
+ LinkageMapELF._ObjectKey.__init__(self, obj, root) |
505 |
+ |
506 |
+ def _generate_object_key(self, obj, root): |
507 |
+ """ |
508 |
+ Generate object key for a given object. |
509 |
+ |
510 |
+ @param object: path to a file |
511 |
+ @type object: string (example: '/usr/bin/bar') |
512 |
+ @rtype: 2-tuple of types (long, int) if object exists. string if |
513 |
+ object does not exist. |
514 |
+ @return: |
515 |
+ 1. 2-tuple of object's inode and device from a stat call, if object |
516 |
+ exists. |
517 |
+ 2. realpath of object if object does not exist. |
518 |
+ |
519 |
+ """ |
520 |
+ |
521 |
+ os = _os_merge |
522 |
+ |
523 |
+ try: |
524 |
+ _unicode_encode(obj, |
525 |
+ encoding=_encodings['merge'], errors='strict') |
526 |
+ except UnicodeEncodeError: |
527 |
+ # The package appears to have been merged with a |
528 |
+ # different value of sys.getfilesystemencoding(), |
529 |
+ # so fall back to utf_8 if appropriate. |
530 |
+ try: |
531 |
+ _unicode_encode(obj, |
532 |
+ encoding=_encodings['fs'], errors='strict') |
533 |
+ except UnicodeEncodeError: |
534 |
+ pass |
535 |
+ else: |
536 |
+ os = portage.os |
537 |
+ |
538 |
+ abs_path = os.path.join(root, obj.lstrip(os.sep)) |
539 |
+ try: |
540 |
+ object_stat = os.stat(abs_path) |
541 |
+ except OSError: |
542 |
+ # Use the realpath as the key if the file does not exists on the |
543 |
+ # filesystem. |
544 |
+ return os.path.realpath(abs_path) |
545 |
+ # Return a tuple of the device and inode, as well as the basename, |
546 |
+ # because of hardlinks the device and inode might be identical. |
547 |
+ return (object_stat.st_dev, object_stat.st_ino, os.path.basename(abs_path.rstrip(os.sep))) |
548 |
+ |
549 |
+ def file_exists(self): |
550 |
+ """ |
551 |
+ Determine if the file for this key exists on the filesystem. |
552 |
+ |
553 |
+ @rtype: Boolean |
554 |
+ @return: |
555 |
+ 1. True if the file exists. |
556 |
+ 2. False if the file does not exist or is a broken symlink. |
557 |
+ |
558 |
+ """ |
559 |
+ return isinstance(self._key, tuple) |
560 |
+ |
561 |
+ class _LibGraphNode(_ObjectKey): |
562 |
+ __slots__ = ("alt_paths",) |
563 |
+ |
564 |
- def __init__(self, obj, root): |
565 |
- LinkageMapXCoff._ObjectKey.__init__(self, obj, root) |
566 |
++ def __init__(self, key): |
567 |
++ """ |
568 |
++ Create a _LibGraphNode from an existing _ObjectKey. |
569 |
++ This re-uses the _key attribute in order to avoid repeating |
570 |
++ any previous stat calls, which helps to avoid potential race |
571 |
++ conditions due to inconsistent stat results when the |
572 |
++ file system is being modified concurrently. |
573 |
++ """ |
574 |
++ self._key = key._key |
575 |
+ self.alt_paths = set() |
576 |
+ |
577 |
+ def __str__(self): |
578 |
+ return str(sorted(self.alt_paths)) |
579 |
+ |
580 |
+ def rebuild(self, exclude_pkgs=None, include_file=None, |
581 |
+ preserve_paths=None): |
582 |
+ """ |
583 |
+ Raises CommandNotFound if there are preserved libs |
584 |
+ and the scanelf binary is not available. |
585 |
+ |
586 |
+ @param exclude_pkgs: A set of packages that should be excluded from |
587 |
+ the LinkageMap, since they are being unmerged and their NEEDED |
588 |
+ entries are therefore irrelevant and would only serve to corrupt |
589 |
+ the LinkageMap. |
590 |
+ @type exclude_pkgs: set |
591 |
+ @param include_file: The path of a file containing NEEDED entries for |
592 |
+ a package which does not exist in the vardbapi yet because it is |
593 |
+ currently being merged. |
594 |
+ @type include_file: String |
595 |
+ @param preserve_paths: Libraries preserved by a package instance that |
596 |
+ is currently being merged. They need to be explicitly passed to the |
597 |
+ LinkageMap, since they are not registered in the |
598 |
+ PreservedLibsRegistry yet. |
599 |
+ @type preserve_paths: set |
600 |
+ """ |
601 |
+ |
602 |
+ os = _os_merge |
603 |
+ root = self._root |
604 |
+ root_len = len(root) - 1 |
605 |
+ self._clear_cache() |
606 |
+ self._defpath.update(getlibpaths(self._root)) |
607 |
+ libs = self._libs |
608 |
+ obj_properties = self._obj_properties |
609 |
+ |
610 |
+ lines = [] |
611 |
+ |
612 |
+ # Data from include_file is processed first so that it |
613 |
+ # overrides any data from previously installed files. |
614 |
+ if include_file is not None: |
615 |
+ for line in grabfile(include_file): |
616 |
+ lines.append((include_file, line)) |
617 |
+ |
618 |
+ aux_keys = [self._needed_aux_key] |
619 |
+ can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK) |
620 |
+ if can_lock: |
621 |
+ self._dbapi.lock() |
622 |
+ try: |
623 |
+ for cpv in self._dbapi.cpv_all(): |
624 |
+ if exclude_pkgs is not None and cpv in exclude_pkgs: |
625 |
+ continue |
626 |
+ needed_file = self._dbapi.getpath(cpv, |
627 |
+ filename=self._needed_aux_key) |
628 |
+ for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines(): |
629 |
+ lines.append((needed_file, line)) |
630 |
+ finally: |
631 |
+ if can_lock: |
632 |
+ self._dbapi.unlock() |
633 |
+ |
634 |
+ # have to call scanelf for preserved libs here as they aren't |
635 |
+ # registered in NEEDED.XCOFF.1 files |
636 |
+ plibs = set() |
637 |
+ if preserve_paths is not None: |
638 |
+ plibs.update(preserve_paths) |
639 |
+ if self._dbapi._plib_registry and \ |
640 |
+ self._dbapi._plib_registry.hasEntries(): |
641 |
+ for cpv, items in \ |
642 |
+ self._dbapi._plib_registry.getPreservedLibs().items(): |
643 |
+ if exclude_pkgs is not None and cpv in exclude_pkgs: |
644 |
+ # These preserved libs will either be unmerged, |
645 |
+ # rendering them irrelevant, or they will be |
646 |
+ # preserved in the replacement package and are |
647 |
+ # already represented via the preserve_paths |
648 |
+ # parameter. |
649 |
+ continue |
650 |
+ plibs.update(items) |
651 |
+ if plibs: |
652 |
+ for x in plibs: |
653 |
+ args = [BASH_BINARY, "-c", ':' |
654 |
+ + '; member="' + x + '"' |
655 |
+ + '; archive=${member}' |
656 |
+ + '; if [[ ${member##*/} == .*"["*"]" ]]' |
657 |
+ + '; then member=${member%/.*}/${member##*/.}' |
658 |
+ + '; archive=${member%[*}' |
659 |
+ + '; fi' |
660 |
+ + '; member=${member#${archive}}' |
661 |
+ + '; [[ -r ${archive} ]] || chmod a+r "${archive}"' |
662 |
+ + '; eval $(aixdll-query "${archive}${member}" FILE MEMBER FLAGS FORMAT RUNPATH DEPLIBS)' |
663 |
+ + '; [[ -n ${member} ]] && needed=${FILE##*/} || needed=' |
664 |
+ + '; for deplib in ${DEPLIBS}' |
665 |
+ + '; do eval deplib=${deplib}' |
666 |
+ + '; if [[ ${deplib} != "." && ${deplib} != ".." ]]' |
667 |
+ + '; then needed="${needed}${needed:+,}${deplib}"' |
668 |
+ + '; fi' |
669 |
+ + '; done' |
670 |
+ + '; [[ -n ${MEMBER} ]] && MEMBER="[${MEMBER}]"' |
671 |
+ + '; [[ " ${FLAGS} " == *" SHROBJ "* ]] && soname=${FILE##*/}${MEMBER} || soname=' |
672 |
+ + '; echo "${FORMAT##* }${FORMAT%%-*};${FILE#${ROOT%/}}${MEMBER};${soname};${RUNPATH};${needed}"' |
673 |
+ + '; [[ -z ${member} && -n ${MEMBER} ]] && echo "${FORMAT##* }${FORMAT%%-*};${FILE#${ROOT%/}};${FILE##*/};;"' |
674 |
+ ] |
675 |
+ try: |
676 |
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE) |
677 |
+ except EnvironmentError as e: |
678 |
+ if e.errno != errno.ENOENT: |
679 |
+ raise |
680 |
+ raise CommandNotFound(args[0]) |
681 |
+ else: |
682 |
+ for l in proc.stdout: |
683 |
+ try: |
684 |
+ l = _unicode_decode(l, |
685 |
+ encoding=_encodings['content'], errors='strict') |
686 |
+ except UnicodeDecodeError: |
687 |
+ l = _unicode_decode(l, |
688 |
+ encoding=_encodings['content'], errors='replace') |
689 |
+ writemsg_level(_("\nError decoding characters " \ |
690 |
+ "returned from aixdll-query: %s\n\n") % (l,), |
691 |
+ level=logging.ERROR, noiselevel=-1) |
692 |
+ l = l.rstrip("\n") |
693 |
+ if not l: |
694 |
+ continue |
695 |
+ fields = l.split(";") |
696 |
+ if len(fields) < 5: |
697 |
+ writemsg_level(_("\nWrong number of fields " \ |
698 |
+ "returned from aixdll-query: %s\n\n") % (l,), |
699 |
+ level=logging.ERROR, noiselevel=-1) |
700 |
+ continue |
701 |
+ fields[1] = fields[1][root_len:] |
702 |
+ plibs.discard(fields[1]) |
703 |
+ lines.append(("aixdll-query", ";".join(fields))) |
704 |
+ proc.wait() |
705 |
+ |
706 |
+ if plibs: |
707 |
+ # Preserved libraries that did not appear in the bash |
708 |
+ # aixdll-query code output. This is known to happen with |
709 |
+ # statically linked libraries. Generate dummy lines for |
710 |
+ # these, so we can assume that every preserved library has |
711 |
+ # an entry in self._obj_properties. This is important in |
712 |
+ # order to prevent findConsumers from raising an unwanted |
713 |
+ # KeyError. |
714 |
+ for x in plibs: |
715 |
+ lines.append(("plibs", ";".join(['', x, '', '', '']))) |
716 |
+ |
717 |
+ for location, l in lines: |
718 |
+ l = l.rstrip("\n") |
719 |
+ if not l: |
720 |
+ continue |
721 |
+ fields = l.split(";") |
722 |
+ if len(fields) < 5: |
723 |
+ writemsg_level(_("\nWrong number of fields " \ |
724 |
+ "in %s: %s\n\n") % (location, l), |
725 |
+ level=logging.ERROR, noiselevel=-1) |
726 |
+ continue |
727 |
+ arch = fields[0] |
728 |
+ |
729 |
+ def as_contentmember(obj): |
730 |
+ if obj.endswith("]"): |
731 |
+ if obj.find("/") >= 0: |
732 |
+ return obj[:obj.rfind("/")] + "/." + obj[obj.rfind("/")+1:] |
733 |
+ return "." + obj |
734 |
+ return obj |
735 |
+ |
736 |
+ obj = as_contentmember(fields[1]) |
737 |
+ soname = as_contentmember(fields[2]) |
738 |
+ path = set([normalize_path(x) \ |
739 |
+ for x in filter(None, fields[3].replace( |
740 |
+ "${ORIGIN}", os.path.dirname(obj)).replace( |
741 |
+ "$ORIGIN", os.path.dirname(obj)).split(":"))]) |
742 |
+ needed = [as_contentmember(x) for x in fields[4].split(",") if x] |
743 |
+ |
744 |
+ obj_key = self._obj_key(obj) |
745 |
+ indexed = True |
746 |
+ myprops = obj_properties.get(obj_key) |
747 |
+ if myprops is None: |
748 |
+ indexed = False |
749 |
+ myprops = (arch, needed, path, soname, set()) |
750 |
+ obj_properties[obj_key] = myprops |
751 |
+ # All object paths are added into the obj_properties tuple. |
752 |
+ myprops[4].add(obj) |
753 |
+ |
754 |
+ # Don't index the same file more that once since only one |
755 |
+ # set of data can be correct and therefore mixing data |
756 |
+ # may corrupt the index (include_file overrides previously |
757 |
+ # installed). |
758 |
+ if indexed: |
759 |
+ continue |
760 |
+ |
761 |
+ arch_map = libs.get(arch) |
762 |
+ if arch_map is None: |
763 |
+ arch_map = {} |
764 |
+ libs[arch] = arch_map |
765 |
+ if soname: |
766 |
+ soname_map = arch_map.get(soname) |
767 |
+ if soname_map is None: |
768 |
+ soname_map = self._soname_map_class( |
769 |
+ providers=set(), consumers=set()) |
770 |
+ arch_map[soname] = soname_map |
771 |
+ soname_map.providers.add(obj_key) |
772 |
+ for needed_soname in needed: |
773 |
+ soname_map = arch_map.get(needed_soname) |
774 |
+ if soname_map is None: |
775 |
+ soname_map = self._soname_map_class( |
776 |
+ providers=set(), consumers=set()) |
777 |
+ arch_map[needed_soname] = soname_map |
778 |
+ soname_map.consumers.add(obj_key) |
779 |
+ |
780 |
+ def getSoname(self, obj): |
781 |
+ """ |
782 |
+ Return the soname associated with an object. |
783 |
+ |
784 |
+ @param obj: absolute path to an object |
785 |
+ @type obj: string (example: '/usr/bin/bar') |
786 |
+ @rtype: string |
787 |
+ @return: soname as a string |
788 |
+ |
789 |
+ """ |
790 |
+ if not self._libs: |
791 |
+ self.rebuild() |
792 |
+ if isinstance(obj, self._ObjectKey): |
793 |
+ obj_key = obj |
794 |
+ if obj_key not in self._obj_properties: |
795 |
+ raise KeyError("%s not in object list" % obj_key) |
796 |
+ return self._obj_properties[obj_key][3] |
797 |
+ if obj not in self._obj_key_cache: |
798 |
+ raise KeyError("%s not in object list" % obj) |
799 |
+ return self._obj_properties[self._obj_key_cache[obj]][3] |
800 |
+ |