Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r11455 - main/trunk/pym/portage/dbapi
Date: Sat, 23 Aug 2008 05:43:16
Message-Id: E1KWlu5-0007T7-CB@stork.gentoo.org
1 Author: zmedico
2 Date: 2008-08-23 05:43:12 +0000 (Sat, 23 Aug 2008)
3 New Revision: 11455
4
5 Modified:
6 main/trunk/pym/portage/dbapi/vartree.py
7 Log:
8 More LinkageMap enhancments from Lucian Poston:
9 * Added _ObjectKey helper class to LinkageMap. (commit eac5528887656abec65fc3a825506187397482e4)
10 * Minor change to docstrings. (commit adde422145d81f25b4024eac1e78b80e1b4a4531)
11
12
13 Modified: main/trunk/pym/portage/dbapi/vartree.py
14 ===================================================================
15 --- main/trunk/pym/portage/dbapi/vartree.py 2008-08-23 02:02:06 UTC (rev 11454)
16 +++ main/trunk/pym/portage/dbapi/vartree.py 2008-08-23 05:43:12 UTC (rev 11455)
17 @@ -139,6 +139,9 @@
18 return rValue
19
20 class LinkageMap(object):
21 +
22 + """Models dynamic linker dependencies."""
23 +
24 def __init__(self, vardbapi):
25 self._dbapi = vardbapi
26 self._libs = {}
27 @@ -146,6 +149,61 @@
28 self._defpath = set(getlibpaths())
29 self._obj_key_cache = {}
30
31 + class _ObjectKey(object):
32 +
33 + """Helper class used as _obj_properties keys for objects."""
34 +
35 + def __init__(self, object):
36 + """
37 + This takes a path to an object.
38 +
39 + @param object: path to a file
40 + @type object: string (example: '/usr/bin/bar')
41 +
42 + """
43 + self._key = self._generate_object_key(object)
44 +
45 + def __hash__(self):
46 + return hash(self._key)
47 +
48 + def __eq__(self, other):
49 + return self._key == other._key
50 +
51 + def _generate_object_key(self, object):
52 + """
53 + Generate object key for a given object.
54 +
55 + @param object: path to a file
56 + @type object: string (example: '/usr/bin/bar')
57 + @rtype: 2-tuple of types (long, int) if object exists. string if
58 + object does not exist.
59 + @return:
60 + 1. 2-tuple of object's inode and device from a stat call, if object
61 + exists.
62 + 2. realpath of object if object does not exist.
63 +
64 + """
65 + try:
66 + object_stat = os.stat(object)
67 + except OSError:
68 + # Use the realpath as the key if the file does not exists on the
69 + # filesystem.
70 + return os.path.realpath(object)
71 + # Return a tuple of the device and inode.
72 + return (object_stat.st_dev, object_stat.st_ino)
73 +
74 + def file_exists(self):
75 + """
76 + Determine if the file for this key exists on the filesystem.
77 +
78 + @rtype: Boolean
79 + @return:
80 + 1. True if the file exists.
81 + 2. False if the file does not exist or is a broken symlink.
82 +
83 + """
84 + return isinstance(self._key, tuple)
85 +
86 def rebuild(self, include_file=None):
87 libs = {}
88 obj_key_cache = {}
89 @@ -179,7 +237,7 @@
90 continue
91 arch = fields[0]
92 obj = fields[1]
93 - obj_key = self._generateObjKey(obj)
94 + obj_key = self._ObjectKey(obj)
95 soname = fields[2]
96 path = set([normalize_path(x)
97 for x in filter(None, fields[3].replace(
98 @@ -206,27 +264,6 @@
99 self._obj_properties = obj_properties
100 self._obj_key_cache = obj_key_cache
101
102 - def _generateObjKey(self, obj):
103 - """
104 - Generate obj key for a given object.
105 -
106 - @param obj: path to an existing file
107 - @type obj: string (example: '/usr/bin/bar')
108 - @rtype: 2-tuple of longs if obj exists. string if obj does not exist.
109 - @return:
110 - 1. 2-tuple of obj's inode and device from a stat call, if obj exists.
111 - 2. realpath of object if obj does not exist.
112 -
113 - """
114 - try:
115 - obj_st = os.stat(obj)
116 - except OSError:
117 - # Use the realpath as the key if the file does not exists on the
118 - # filesystem.
119 - return os.path.realpath(obj)
120 - # Return a tuple of the device and inode.
121 - return (obj_st.st_dev, obj_st.st_ino)
122 -
123 def listBrokenBinaries(self, debug=False):
124 """
125 Find binaries and their needed sonames, which have no providers.
126 @@ -239,13 +276,13 @@
127 object that have no corresponding libraries to fulfill the dependency.
128
129 """
130 - class LibraryCache(object):
131 + class _LibraryCache(object):
132
133 """
134 Caches properties associated with paths.
135
136 - The purpose of this class is to prevent multiple calls of
137 - _generateObjKey on the same paths.
138 + The purpose of this class is to prevent multiple instances of
139 + _ObjectKey for the same paths.
140
141 """
142
143 @@ -274,9 +311,9 @@
144 if obj in self._obj_key_cache:
145 obj_key = self._obj_key_cache.get(obj)
146 else:
147 - obj_key = self._generateObjKey(obj)
148 + obj_key = self._ObjectKey(obj)
149 # Check that the library exists on the filesystem.
150 - if isinstance(obj_key, tuple):
151 + if obj_key.file_exists():
152 # Get the arch and soname from LinkageMap._obj_properties if
153 # it exists. Otherwise, None.
154 arch, _, _, soname, _ = \
155 @@ -288,7 +325,7 @@
156 (None, None, obj_key, False))
157
158 rValue = {}
159 - cache = LibraryCache()
160 + cache = _LibraryCache()
161 providers = self.listProviders()
162
163 # Iterate over all obj_keys and their providers.
164 @@ -372,7 +409,7 @@
165 self.rebuild()
166 # Iterate over all object keys within LinkageMap.
167 for obj_key in self._obj_properties:
168 - rValue.setdefault(obj_key, self.findProviders(obj_key=obj_key))
169 + rValue.setdefault(obj_key, self.findProviders(obj_key))
170 return rValue
171
172 def isMasterLink(self, obj):
173 @@ -388,7 +425,7 @@
174
175 """
176 basename = os.path.basename(obj)
177 - obj_key = self._generateObjKey(obj)
178 + obj_key = self._ObjectKey(obj)
179 if obj_key not in self._obj_properties:
180 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
181 soname = self._obj_properties[obj_key][3]
182 @@ -429,13 +466,11 @@
183 raise KeyError("%s not in object list" % obj)
184 return self._obj_properties[self._obj_key_cache[obj]][3]
185
186 - def findProviders(self, obj=None, obj_key=None):
187 + def findProviders(self, obj):
188 """
189 Find providers for an object or object key.
190
191 - This method should be called with either an obj or obj_key. If called
192 - with both, the obj_key is ignored. If called with neither, KeyError is
193 - raised as if an invalid obj was passed.
194 + This method may be called with a key from _obj_properties.
195
196 In some cases, not all valid libraries are returned. This may occur when
197 an soname symlink referencing a library is in an object's runpath while
198 @@ -444,10 +479,8 @@
199 library dependencies (since the dynamic linker actually searches for
200 files named with the soname in the runpaths).
201
202 - @param obj: absolute path to an object
203 - @type obj: string (example: '/usr/bin/bar')
204 - @param obj_key: key from LinkageMap._generateObjKey
205 - @type obj_key: 2-tuple of longs or string
206 + @param obj: absolute path to an object or a key from _obj_properties
207 + @type obj: string (example: '/usr/bin/bar') or _ObjectKey
208 @rtype: dict (example: {'libbar.so': set(['/lib/libbar.so.1.5'])})
209 @return: The return value is a soname -> set-of-library-paths, where
210 set-of-library-paths satisfy soname.
211 @@ -459,14 +492,16 @@
212 self.rebuild()
213
214 # Determine the obj_key from the arguments.
215 - if obj is not None:
216 + if isinstance(obj, self._ObjectKey):
217 + obj_key = obj
218 + if obj_key not in self._obj_properties:
219 + raise KeyError("%s not in object list" % obj_key)
220 + else:
221 obj_key = self._obj_key_cache.get(obj)
222 if obj_key not in self._obj_properties:
223 - obj_key = self._generateObjKey(obj)
224 + obj_key = self._ObjectKey(obj)
225 if obj_key not in self._obj_properties:
226 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
227 - elif obj_key not in self._obj_properties:
228 - raise KeyError("%s not in object list" % obj_key)
229
230 arch, needed, path, _, _ = self._obj_properties[obj_key]
231 path = path.union(self._defpath)
232 @@ -483,23 +518,22 @@
233 rValue[soname].add(provider)
234 return rValue
235
236 - def findConsumers(self, obj=None, obj_key=None):
237 + def findConsumers(self, obj):
238 """
239 Find consumers of an object or object key.
240
241 - This method should be called with either an obj or obj_key. If called
242 - with both, the obj_key is ignored. If called with neither, KeyError is
243 - raised as if an invalid obj was passed.
244 + This method may be called with a key from _obj_properties. If this
245 + method is going to be called with an object key, to avoid not catching
246 + shadowed libraries, do not pass new _ObjectKey instances to this method.
247 + Instead pass the obj as a string.
248
249 In some cases, not all consumers are returned. This may occur when
250 an soname symlink referencing a library is in an object's runpath while
251 the actual library is not.
252
253 - @param obj: absolute path to an object
254 - @type obj: string (example: '/usr/bin/bar')
255 - @param obj_key: key from LinkageMap._generateObjKey
256 - @type obj_key: 2-tuple of longs or string
257 - @rtype: set of strings (example: )
258 + @param obj: absolute path to an object or a key from _obj_properties
259 + @type obj: string (example: '/usr/bin/bar') or _ObjectKey
260 + @rtype: set of strings (example: set(['/bin/foo', '/usr/bin/bar']))
261 @return: The return value is a soname -> set-of-library-paths, where
262 set-of-library-paths satisfy soname.
263
264 @@ -510,17 +544,18 @@
265 self.rebuild()
266
267 # Determine the obj_key and the set of objects matching the arguments.
268 - if obj is not None:
269 + if isinstance(obj, self._ObjectKey):
270 + obj_key = obj
271 + if obj_key not in self._obj_properties:
272 + raise KeyError("%s not in object list" % obj_key)
273 + objs = self._obj_properties[obj_key][4]
274 + else:
275 objs = set([obj])
276 obj_key = self._obj_key_cache.get(obj)
277 if obj_key not in self._obj_properties:
278 - obj_key = self._generateObjKey(obj)
279 + obj_key = self._ObjectKey(obj)
280 if obj_key not in self._obj_properties:
281 raise KeyError("%s (%s) not in object list" % (obj_key, obj))
282 - else:
283 - if obj_key not in self._obj_properties:
284 - raise KeyError("%s not in object list" % obj_key)
285 - objs = self._obj_properties[obj_key][4]
286
287 # Determine the directory(ies) from the set of objects.
288 objs_dirs = set([os.path.dirname(x) for x in objs])
289 @@ -529,7 +564,7 @@
290 # same soname and the master link points to that
291 # other version, this lib will be shadowed and won't
292 # have any consumers.
293 - if obj is not None:
294 + if not isinstance(obj, self._ObjectKey):
295 soname = self._obj_properties[obj_key][3]
296 obj_dir = os.path.dirname(obj)
297 master_link = os.path.join(obj_dir, soname)