Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:prefix commit in: pym/portage/util/_dyn_libs/
Date: Tue, 26 Jul 2011 17:35:25
Message-Id: 71a47b1875141b038489ab87b87f7f5eb1e7332b.grobian@gentoo
1 commit: 71a47b1875141b038489ab87b87f7f5eb1e7332b
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Tue Jul 26 17:23:06 2011 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Tue Jul 26 17:23:06 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=71a47b18
7
8 LinkageMapMachO: sync with LinkageMapELF
9
10 ---
11 pym/portage/util/_dyn_libs/LinkageMapMachO.py | 153 +++++++++++++++++++------
12 1 files changed, 116 insertions(+), 37 deletions(-)
13
14 diff --git a/pym/portage/util/_dyn_libs/LinkageMapMachO.py b/pym/portage/util/_dyn_libs/LinkageMapMachO.py
15 index e64a54d..0e7c333 100644
16 --- a/pym/portage/util/_dyn_libs/LinkageMapMachO.py
17 +++ b/pym/portage/util/_dyn_libs/LinkageMapMachO.py
18 @@ -27,6 +27,18 @@ class LinkageMapMachO(object):
19 _installname_map_class = slot_dict_class(
20 ("consumers", "providers"), prefix="")
21
22 + class _obj_properies_class(object):
23 +
24 + __slots__ = ("arch", "needed", "install_name", "alt_paths",
25 + "owner",)
26 +
27 + def __init__(self, arch, needed, install_name, alt_paths, owner):
28 + self.arch = arch
29 + self.needed = needed
30 + self.install_name = install_name
31 + self.alt_paths = alt_paths
32 + self.owner = owner
33 +
34 def __init__(self, vardbapi):
35 self._dbapi = vardbapi
36 self._root = self._dbapi.settings['ROOT']
37 @@ -183,7 +195,7 @@ class LinkageMapMachO(object):
38 # overrides any data from previously installed files.
39 if include_file is not None:
40 for line in grabfile(include_file):
41 - lines.append((include_file, line))
42 + lines.append((None, include_file, line))
43
44 aux_keys = [self._needed_aux_key]
45 can_lock = os.access(os.path.dirname(self._dbapi._dbroot), os.W_OK)
46 @@ -196,16 +208,16 @@ class LinkageMapMachO(object):
47 needed_file = self._dbapi.getpath(cpv,
48 filename=self._needed_aux_key)
49 for line in self._dbapi.aux_get(cpv, aux_keys)[0].splitlines():
50 - lines.append((needed_file, line))
51 + lines.append((cpv, needed_file, line))
52 finally:
53 if can_lock:
54 self._dbapi.unlock()
55
56 # have to call scanmacho for preserved libs here as they aren't
57 # registered in NEEDED.MACHO.3 files
58 - plibs = set()
59 + plibs = {}
60 if preserve_paths is not None:
61 - plibs.update(preserve_paths)
62 + plibs.update((x, None) for x in preserve_paths)
63 if self._dbapi._plib_registry and \
64 self._dbapi._plib_registry.hasEntries():
65 for cpv, items in \
66 @@ -217,7 +229,7 @@ class LinkageMapMachO(object):
67 # already represented via the preserve_paths
68 # parameter.
69 continue
70 - plibs.update(items)
71 + plibs.update((x, cpv) for x in items)
72 if plibs:
73 args = [EPREFIX+"/usr/bin/scanmacho", "-qF", "%a;%F;%S;%n"]
74 args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
75 @@ -249,8 +261,8 @@ class LinkageMapMachO(object):
76 level=logging.ERROR, noiselevel=-1)
77 continue
78 fields[1] = fields[1][root_len:]
79 - plibs.discard(fields[1])
80 - lines.append(("scanmacho", ";".join(fields)))
81 + owner = plibs.pop(fields[1], None)
82 + lines.append((owner, "scanmacho", ";".join(fields)))
83 proc.wait()
84
85 if plibs:
86 @@ -260,33 +272,39 @@ class LinkageMapMachO(object):
87 # assume that every preserved library has an entry in
88 # self._obj_properties. This is important in order to
89 # prevent findConsumers from raising an unwanted KeyError.
90 - for x in plibs:
91 - lines.append(("plibs", ";".join(['', x, '', '', ''])))
92 + for x, cpv in plibs.items():
93 + lines.append((cpv, "plibs", ";".join(['', x, '', '', ''])))
94
95 - for location, l in lines:
96 + # Share identical frozenset instances when available,
97 + # in order to conserve memory.
98 + frozensets = {}
99 +
100 + for owner, location, l in lines:
101 l = l.rstrip("\n")
102 if not l:
103 continue
104 fields = l.split(";")
105 if len(fields) < 4:
106 - writemsg_level("\nWrong number of fields " + \
107 - "in %s: %s\n\n" % (location, l),
108 + writemsg_level(_("\nWrong number of fields " \
109 + "in %s: %s\n\n") % (location, l),
110 level=logging.ERROR, noiselevel=-1)
111 continue
112 arch = fields[0]
113 obj = fields[1]
114 install_name = os.path.normpath(fields[2])
115 - needed = filter(None, fields[3].split(","))
116 + needed = frozenset(x for x in fields[3].split(",") if x)
117 + needed = frozensets.setdefault(needed, needed)
118
119 obj_key = self._obj_key(obj)
120 indexed = True
121 myprops = obj_properties.get(obj_key)
122 if myprops is None:
123 indexed = False
124 - myprops = (arch, needed, install_name, set())
125 + myprops = self._obj_properies_class(
126 + arch, needed, install_name, [], owner)
127 obj_properties[obj_key] = myprops
128 # All object paths are added into the obj_properties tuple.
129 - myprops[3].add(obj)
130 + myprops.alt_paths.append(obj)
131
132 # Don't index the same file more that once since only one
133 # set of data can be correct and therefore mixing data
134 @@ -303,17 +321,22 @@ class LinkageMapMachO(object):
135 installname_map = arch_map.get(install_name)
136 if installname_map is None:
137 installname_map = self._installname_map_class(
138 - providers=set(), consumers=set())
139 + providers=[], consumers=[])
140 arch_map[install_name] = installname_map
141 installname_map.providers.add(obj_key)
142 for needed_installname in needed:
143 installname_map = arch_map.get(needed_installname)
144 if installname_map is None:
145 installname_map = self._installname_map_class(
146 - providers=set(), consumers=set())
147 + providers=[], consumers=[])
148 arch_map[needed_installname] = installname_map
149 installname_map.consumers.add(obj_key)
150
151 + for arch, install_names in libs.items():
152 + for install_name_node in install_names.values():
153 + install_name_node.providers = tuple(set(install_name_node.providers))
154 + install_name_node.consumers = tuple(set(install_name_node.consumers))
155 +
156 def listBrokenBinaries(self, debug=False):
157 """
158 Find binaries and their needed install_names, which have no providers.
159 @@ -367,8 +390,13 @@ class LinkageMapMachO(object):
160 if obj_key.file_exists():
161 # Get the install_name from LinkageMapMachO._obj_properties if
162 # it exists. Otherwise, None.
163 - arch = self._obj_properties.get(obj_key, (None,)*4)[0]
164 - install_name = self._obj_properties.get(obj_key, (None,)*4)[2]
165 + obj_props = self._obj_properties.get(obj_key)
166 + if obj_props is None:
167 + arch = None
168 + install_name = None
169 + else:
170 + arch = obj_props.arch
171 + install_name = obj_props.install_name
172 return cache_self.cache.setdefault(obj, \
173 (arch, install_name, obj_key, True))
174 else:
175 @@ -381,8 +409,9 @@ class LinkageMapMachO(object):
176
177 # Iterate over all obj_keys and their providers.
178 for obj_key, install_names in providers.items():
179 - arch = self._obj_properties[obj_key][0]
180 - objs = self._obj_properties[obj_key][3]
181 + obj_props = self._obj_properties[obj_key]
182 + arch = obj_props.arch
183 + objs = obj_props.alt_paths
184 # Iterate over each needed install_name and the set of
185 # library paths that fulfill the install_name to determine
186 # if the dependency is broken.
187 @@ -483,7 +512,7 @@ class LinkageMapMachO(object):
188 if obj_key not in self._obj_properties:
189 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
190 basename = os.path.basename(obj)
191 - install_name = self._obj_properties[obj_key][2]
192 + install_name = self._obj_properties[obj_key].install_name
193 return (len(basename) < len(os.path.basename(install_name)) and \
194 basename.endswith(".dylib") and \
195 os.path.basename(install_name).startswith(basename[:-6]))
196 @@ -504,9 +533,40 @@ class LinkageMapMachO(object):
197 for arch_map in self._libs.values():
198 for soname_map in arch_map.values():
199 for obj_key in soname_map.providers:
200 - rValue.extend(self._obj_properties[obj_key][3])
201 + rValue.extend(self._obj_properties[obj_key].alt_paths)
202 return rValue
203
204 + def getOwners(self, obj):
205 + """
206 + Return the package(s) associated with an object. Raises KeyError
207 + if the object is unknown. Returns an empty tuple if the owner(s)
208 + are unknown.
209 +
210 + NOTE: For preserved libraries, the owner(s) may have been
211 + previously uninstalled, but these uninstalled owners can be
212 + returned by this method since they are registered in the
213 + PreservedLibsRegistry.
214 +
215 + @param obj: absolute path to an object
216 + @type obj: string (example: '/usr/bin/bar')
217 + @rtype: tuple
218 + @return: a tuple of cpv
219 + """
220 + if not self._libs:
221 + self.rebuild()
222 + if isinstance(obj, self._ObjectKey):
223 + obj_key = obj
224 + else:
225 + obj_key = self._obj_key_cache.get(obj)
226 + if obj_key is None:
227 + raise KeyError("%s not in object list" % obj)
228 + obj_props = self._obj_properties.get(obj_key)
229 + if obj_props is None:
230 + raise KeyError("%s not in object list" % obj_key)
231 + if obj_props.owner is None:
232 + return ()
233 + return (obj_props.owner,)
234 +
235 def getSoname(self, obj):
236 """
237 Return the soname associated with an object.
238 @@ -523,10 +583,10 @@ class LinkageMapMachO(object):
239 obj_key = obj
240 if obj_key not in self._obj_properties:
241 raise KeyError("%s not in object list" % obj_key)
242 - return self._obj_properties[obj_key][2]
243 + return self._obj_properties[obj_key].install_name
244 if obj not in self._obj_key_cache:
245 raise KeyError("%s not in object list" % obj)
246 - return self._obj_properties[self._obj_key_cache[obj]][2]
247 + return self._obj_properties[self._obj_key_cache[obj]].install_name
248
249 def findProviders(self, obj):
250 """
251 @@ -566,7 +626,10 @@ class LinkageMapMachO(object):
252 if obj_key not in self._obj_properties:
253 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
254
255 - arch, needed, install_name, _ = self._obj_properties[obj_key]
256 + obj_props = self._obj_properties[obj_key]
257 + arch = obj_props.arch
258 + needed = obj_props.needed
259 + install_name = obj_props.install_name
260 for install_name in needed:
261 rValue[install_name] = set()
262 if arch not in self._libs or install_name not in self._libs[arch]:
263 @@ -574,13 +637,13 @@ class LinkageMapMachO(object):
264 # For each potential provider of the install_name, add it to
265 # rValue if it exists. (Should be one)
266 for provider_key in self._libs[arch][install_name].providers:
267 - providers = self._obj_properties[provider_key][3]
268 + providers = self._obj_properties[provider_key].alt_paths
269 for provider in providers:
270 if os.path.exists(provider):
271 rValue[install_name].add(provider)
272 return rValue
273
274 - def findConsumers(self, obj):
275 + def findConsumers(self, obj, exclude_providers=None):
276 """
277 Find consumers of an object or object key.
278
279 @@ -603,8 +666,16 @@ class LinkageMapMachO(object):
280 corresponding libtool archive (*.la) files to detect such consumers
281 (revdep-rebuild is able to detect them).
282
283 + The exclude_providers argument is only useful on platforms where
284 + references to libraries are not full paths, e.g. they are being
285 + searched for in a path, like ELF. On Mach-O, these references
286 + are full paths, and hence this argument is ignored, since there
287 + never will be alternative providers.
288 +
289 @param obj: absolute path to an object or a key from _obj_properties
290 @type obj: string (example: '/usr/bin/bar') or _ObjectKey
291 + @param exclude_providers: ignored in LinkageMapMachO
292 + @type exclude_providers: collection
293 @rtype: set of strings (example: set(['/bin/foo', '/usr/bin/bar']))
294 @return: The return value is a install_name -> set-of-library-paths, where
295 set-of-library-paths satisfy install_name.
296 @@ -613,8 +684,6 @@ class LinkageMapMachO(object):
297
298 os = _os_merge
299
300 - rValue = set()
301 -
302 if not self._libs:
303 self.rebuild()
304
305 @@ -623,7 +692,7 @@ class LinkageMapMachO(object):
306 obj_key = obj
307 if obj_key not in self._obj_properties:
308 raise KeyError("%s not in object list" % obj_key)
309 - objs = self._obj_properties[obj_key][3]
310 + objs = self._obj_properties[obj_key].alt_paths
311 else:
312 objs = set([obj])
313 obj_key = self._obj_key(obj)
314 @@ -635,7 +704,7 @@ class LinkageMapMachO(object):
315 # other version, this lib will be shadowed and won't
316 # have any consumers.
317 if not isinstance(obj, self._ObjectKey):
318 - install_name = self._obj_properties[obj_key][2]
319 + install_name = self._obj_properties[obj_key].install_name
320 master_link = os.path.join(self._root,
321 install_name.lstrip(os.path.sep))
322 try:
323 @@ -648,12 +717,22 @@ class LinkageMapMachO(object):
324 (master_st.st_dev, master_st.st_ino):
325 return set()
326
327 - arch = self._obj_properties[obj_key][0]
328 - install_name = self._obj_properties[obj_key][2]
329 - if arch in self._libs and install_name in self._libs[arch]:
330 + obj_props = self._obj_properties[obj_key]
331 + arch = obj_props.arch
332 + install_name = obj_props.install_name
333 +
334 + install_name_node = None
335 + arch_map = self._libs.get(arch)
336 + if arch_map is not None:
337 + install_name_node = arch_map.get(install_name)
338 +
339 +
340 + rValue = set()
341 + if install_name_node is not None:
342 # For each potential consumer, add it to rValue if an object from the
343 # arguments resides in the consumer's runpath.
344 - for consumer_key in self._libs[arch][install_name].consumers:
345 - consumer_objs = self._obj_properties[consumer_key][3]
346 + for consumer_key in install_name_node.consumers:
347 + consumer_props = self._obj_properties[consumer_key]
348 + consumer_objs = consumer_props.alt_paths
349 rValue.update(consumer_objs)
350 return rValue