1 |
Author: grobian |
2 |
Date: 2008-05-02 14:40:49 +0000 (Fri, 02 May 2008) |
3 |
New Revision: 10089 |
4 |
|
5 |
Added: |
6 |
main/branches/prefix/pym/portage/sets/libs.py |
7 |
Modified: |
8 |
main/branches/prefix/bin/emerge-webrsync |
9 |
main/branches/prefix/bin/misc-functions.sh |
10 |
main/branches/prefix/cnf/sets.conf |
11 |
main/branches/prefix/doc/config/sets.docbook |
12 |
main/branches/prefix/pym/_emerge/__init__.py |
13 |
main/branches/prefix/pym/portage/dbapi/vartree.py |
14 |
main/branches/prefix/pym/portage/sets/__init__.py |
15 |
main/branches/prefix/pym/portage/sets/base.py |
16 |
main/branches/prefix/pym/portage/sets/dbapi.py |
17 |
main/branches/prefix/pym/portage/sets/files.py |
18 |
Log: |
19 |
Merged from trunk 10069:10086 |
20 |
|
21 |
| 10070 | Skip group/owner tarsync options for tarsync if chown on | |
22 |
| zmedico | /usr/portage fails, since the user might still be able to | |
23 |
| | sync even though the chown call is not permitted. | |
24 |
|
25 |
| 10072 | Fix broken variable references found by pyflakes. | |
26 |
| zmedico | | |
27 |
|
28 |
| 10073 | remove 'sets/' name-prefix for file-based package sets | |
29 |
| genone | | |
30 |
|
31 |
| 10075 | check if a given package set is defined more than once | |
32 |
| genone | | |
33 |
|
34 |
| 10077 | add config option for package sets to not be recorded in | |
35 |
| genone | 'world' | |
36 |
|
37 |
| 10078 | properly remove sets from 'world' when unmerging | |
38 |
| genone | | |
39 |
|
40 |
| 10079 | move cleaning of sets out of package loop | |
41 |
| genone | | |
42 |
|
43 |
| 10080 | do not consider sets to be installed that are about to be | |
44 |
| genone | unmerged | |
45 |
|
46 |
| 10081 | v2 of FEATURES=preserved-libs, using LinkageMap instead of | |
47 |
| genone | the now removed LibraryPackageMap class | |
48 |
|
49 |
| 10082 | use special symlink comparison code (original patch from | |
50 |
| genone | prefix r9499) | |
51 |
|
52 |
| 10083 | fix typo | |
53 |
| genone | | |
54 |
|
55 |
| 10085 | rename NEEDED.2 to NEEDED.ELF.2 to allow other ABI formats | |
56 |
| genone | to use a different syntax | |
57 |
|
58 |
| 10086 | Update documentation for package set configuration. Original | |
59 |
| genone | patch by Arfrever Frehtes Taifersar Arahesis | |
60 |
|
61 |
|
62 |
Modified: main/branches/prefix/bin/emerge-webrsync |
63 |
=================================================================== |
64 |
--- main/branches/prefix/bin/emerge-webrsync 2008-05-02 14:39:08 UTC (rev 10088) |
65 |
+++ main/branches/prefix/bin/emerge-webrsync 2008-05-02 14:40:49 UTC (rev 10089) |
66 |
@@ -174,7 +174,10 @@ |
67 |
vecho "Syncing local tree ..." |
68 |
|
69 |
if type -P tarsync > /dev/null ; then |
70 |
- if ! tarsync $(vvecho -v) -s 1 -o portage -g portage -e /distfiles -e /packages -e /local "${file}" "${PORTDIR}"; then |
71 |
+ local chown_opts="-o portage -g portage" |
72 |
+ chown portage:portage portage > /dev/null 2>&1 || chown_opts="" |
73 |
+ if ! tarsync $(vvecho -v) -s 1 ${chown_opts} \ |
74 |
+ -e /distfiles -e /packages -e /local "${file}" "${PORTDIR}"; then |
75 |
eecho "tarsync failed; tarball is corrupt? (${file})" |
76 |
return 1 |
77 |
fi |
78 |
|
79 |
Modified: main/branches/prefix/bin/misc-functions.sh |
80 |
=================================================================== |
81 |
--- main/branches/prefix/bin/misc-functions.sh 2008-05-02 14:39:08 UTC (rev 10088) |
82 |
+++ main/branches/prefix/bin/misc-functions.sh 2008-05-02 14:40:49 UTC (rev 10089) |
83 |
@@ -169,7 +169,7 @@ |
84 |
if [ -z "${rpath}" -o -n "${rpath//*ORIGIN*}" ]; then |
85 |
# object doesn't contain $ORIGIN in its runpath attribute |
86 |
echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED |
87 |
- echo "${arch:3};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.2 |
88 |
+ echo "${arch:3};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2 |
89 |
else |
90 |
dir=$(dirname ${obj}) |
91 |
# replace $ORIGIN with the dirname of the current object for the lookup |
92 |
@@ -186,7 +186,7 @@ |
93 |
rneeded=${rneeded:1} |
94 |
if [ -n "${rneeded}" ]; then |
95 |
echo "${obj} ${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED |
96 |
- echo "${arch:3};${obj};${soname};${rpath};${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.2 |
97 |
+ echo "${arch:3};${obj};${soname};${rpath};${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2 |
98 |
fi |
99 |
fi |
100 |
done } |
101 |
|
102 |
Modified: main/branches/prefix/cnf/sets.conf |
103 |
=================================================================== |
104 |
--- main/branches/prefix/cnf/sets.conf 2008-05-02 14:39:08 UTC (rev 10088) |
105 |
+++ main/branches/prefix/cnf/sets.conf 2008-05-02 14:40:49 UTC (rev 10089) |
106 |
@@ -7,6 +7,7 @@ |
107 |
# Not much that could be changed for world, so better leave it alone |
108 |
[world] |
109 |
class = portage.sets.files.WorldSet |
110 |
+world-candidate = False |
111 |
|
112 |
# Same as for world, though later portage versions might use a different class |
113 |
[system] |
114 |
@@ -21,13 +22,15 @@ |
115 |
# - SecuritySet: include all GLSAs |
116 |
[security] |
117 |
class = portage.sets.security.NewAffectedSet |
118 |
+world-candidate = False |
119 |
|
120 |
# Again, not much to change here, though people might prefer a different name |
121 |
[everything] |
122 |
class = portage.sets.dbapi.EverythingSet |
123 |
+world-candidate = False |
124 |
|
125 |
# The following treats all files in /etc/portage/sets as a package set called |
126 |
-# 'sets/$filename'. |
127 |
+# '$filename'. |
128 |
[usersets] |
129 |
class = portage.sets.files.StaticFileSet |
130 |
multiset = true |
131 |
@@ -36,4 +39,5 @@ |
132 |
# Set to rebuild all packages that need a preserved lib that only remains due |
133 |
# to FEATURES=preserve-libs |
134 |
[preserved-rebuild] |
135 |
-class = portage.sets.dbapi.PreservedLibraryConsumerSet |
136 |
+class = portage.sets.libs.PreservedLibraryConsumerSet |
137 |
+world-candidate = False |
138 |
|
139 |
Modified: main/branches/prefix/doc/config/sets.docbook |
140 |
=================================================================== |
141 |
--- main/branches/prefix/doc/config/sets.docbook 2008-05-02 14:39:08 UTC (rev 10088) |
142 |
+++ main/branches/prefix/doc/config/sets.docbook 2008-05-02 14:40:49 UTC (rev 10089) |
143 |
@@ -49,12 +49,13 @@ |
144 |
isn't stricly required, but it should always be used as the default |
145 |
handler might be changed in future versions.</para></footnote>. |
146 |
That option defines which handler class should be used to |
147 |
- create the set. Another universal option available for single sets is |
148 |
- <varname>name</varname>, however it's usually not needed as the name |
149 |
+ create the set. Other universal options available for single sets are |
150 |
+ <varname>name</varname> (which is usually not needed as the name |
151 |
of the set is generated from the section name if <varname>name</varname> |
152 |
- is missing. Some handler classes might require additional |
153 |
- options for their configuration, these will be covered later in |
154 |
- this chapter. |
155 |
+ is missing) and <varname>world-candidate</varname>, which determines if |
156 |
+ given package should be added to the <varname>world</varname> set. Some |
157 |
+ handler classes might require additional options for their configuration, |
158 |
+ these will be covered later in this chapter. |
159 |
</para> |
160 |
<para> |
161 |
Here are a few examples for single sets taken from the default |
162 |
@@ -63,6 +64,7 @@ |
163 |
# The classic world set |
164 |
[world] |
165 |
class = portage.sets.files.WorldSet |
166 |
+ world-candidate = False |
167 |
|
168 |
# The classic system set |
169 |
[system] |
170 |
@@ -81,7 +83,8 @@ |
171 |
sets each section still requires the <varname>class</varname> option, |
172 |
but to indicate that the section should generate multiple sets it's |
173 |
also necessary to set the <varname>multiset</varname> option to |
174 |
- <parameter>true</parameter>. |
175 |
+ <parameter>true</parameter>. The <varname>world-candidate</varname> |
176 |
+ option is also supported like with single sets. |
177 |
</para> |
178 |
<para> |
179 |
As it doesn't make much sense to specify a single name for multiple sets |
180 |
@@ -157,6 +160,11 @@ |
181 |
<itemizedlist> |
182 |
<listitem><varname>filename</varname>: Required. Specifies the path to the file |
183 |
that should be used for the package set.</listitem> |
184 |
+ <listitem><varname>greedy</varname>: Optional, defaults to <parameter>false</parameter>. |
185 |
+ Determines if atoms in the package should include all installed slots (when set to |
186 |
+ <parameter>true</parameter>) or if no slot expansion is wanted (when set to |
187 |
+ <parameter>false</parameter>). This option only affects packages that have multiple |
188 |
+ slots available (e.g. <parameter>sys-kernel/gentoo-sources</parameter>).</listitem> |
189 |
</itemizedlist> |
190 |
</para> |
191 |
</sect3> |
192 |
@@ -172,7 +180,7 @@ |
193 |
that location a separate package set is created. |
194 |
</listitem> |
195 |
<listitem><varname>name_pattern</varname>: Optional, defaults to |
196 |
- <parameter>sets/$name</parameter>. This describes the naming pattern |
197 |
+ <parameter>$name</parameter>. This describes the naming pattern |
198 |
to be used for creating the sets. It must contain either |
199 |
<parameter>$name</parameter> or <parameter>${name}</parameter>, which |
200 |
will be replaced by the filename (without any directory components). |
201 |
@@ -218,7 +226,7 @@ |
202 |
No other files in that directory will be used. |
203 |
</listitem> |
204 |
<listitem><varname>name_pattern</varname>: Optional, defaults to |
205 |
- <parameter>sets/package_$suffix</parameter>. This describes the naming |
206 |
+ <parameter>package_$suffix</parameter>. This describes the naming |
207 |
pattern to be used for creating the sets. It must contain either |
208 |
<parameter>$suffix</parameter> or <parameter>${suffix}</parameter>, |
209 |
which will be replaced by the file suffix (e.g. |
210 |
@@ -240,7 +248,7 @@ |
211 |
<sect3> |
212 |
<title>Single Set Configuraton</title> |
213 |
<para> |
214 |
- This class does not support any options. |
215 |
+ This class doesn't support any extra options. |
216 |
</para> |
217 |
</sect3> |
218 |
</sect2> |
219 |
@@ -258,7 +266,7 @@ |
220 |
<sect3> |
221 |
<title>Single Set Configuration</title> |
222 |
<para> |
223 |
- This class does not support any options. |
224 |
+ This class doesn't support any extra options. |
225 |
</para> |
226 |
</sect3> |
227 |
</sect2> |
228 |
@@ -441,10 +449,29 @@ |
229 |
<sect3> |
230 |
<title>Single Set Configuration</title> |
231 |
<para> |
232 |
- This class does not support any options. |
233 |
+ This class doesn't support any extra options. |
234 |
</para> |
235 |
</sect3> |
236 |
</sect2> |
237 |
+ <sect2 id='config-set-classes-PreservedLibraryConsumerSet'> |
238 |
+ <title>portage.sets.libs.PreservedLibraryConsumerSet</title> |
239 |
+ <para> |
240 |
+ A special set used to rebuild all packages that need a preserved library that only |
241 |
+ remains due to <varname>FEATURES="preserve-libs"</varname>. |
242 |
+ </para> |
243 |
+ |
244 |
+ <sect3> |
245 |
+ <title>Single Set Configuration</title> |
246 |
+ <para> |
247 |
+ This class supports the following option: |
248 |
+ <itemizedlist> |
249 |
+ <listitem><varname>debug</varname>: Generate extra output useful to figure out why |
250 |
+ certain packages are included in the set, as it's not always obvious. |
251 |
+ </listitem> |
252 |
+ </itemizedlist> |
253 |
+ </para> |
254 |
+ </sect3> |
255 |
+ </sect2> |
256 |
</sect1> |
257 |
|
258 |
<sect1 id='config-set-defaults'> |
259 |
@@ -462,6 +489,7 @@ |
260 |
<listitem><varname>world</varname>: uses <classname>WorldSet</classname></listitem> |
261 |
<listitem><varname>security</varname>: uses <classname>NewAffectedSet</classname> with default options</listitem> |
262 |
<listitem><varname>everything</varname>: uses <classname>EverythingSet</classname></listitem> |
263 |
+ <listitem><varname>preserved-rebuild</varname>: uses <classname>PreservedLibraryConsumerSet</classname></listitem> |
264 |
</itemizedlist> |
265 |
Additionally the default configuration includes a multi set section based on |
266 |
the <classname>StaticFileSet</classname> defaults that creates a set for each |
267 |
|
268 |
Modified: main/branches/prefix/pym/_emerge/__init__.py |
269 |
=================================================================== |
270 |
--- main/branches/prefix/pym/_emerge/__init__.py 2008-05-02 14:39:08 UTC (rev 10088) |
271 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2008-05-02 14:40:49 UTC (rev 10089) |
272 |
@@ -3207,7 +3207,7 @@ |
273 |
blockers is not None: |
274 |
# Re-use the blockers from the graph. |
275 |
blocker_atoms = sorted(blockers) |
276 |
- counter = long(node.metadata["COUNTER"]) |
277 |
+ counter = long(pkg.metadata["COUNTER"]) |
278 |
blocker_data = \ |
279 |
blocker_cache.BlockerData(counter, blocker_atoms) |
280 |
blocker_cache[pkg.cpv] = blocker_data |
281 |
@@ -4238,9 +4238,7 @@ |
282 |
counters.newslot += 1 |
283 |
|
284 |
if "--changelog" in self.myopts: |
285 |
- slot_atom = "%s:%s" % (portage.dep_getkey(pkg_key), |
286 |
- mydbapi.aux_get(pkg_key, ["SLOT"])[0]) |
287 |
- inst_matches = vardb.match(slot_atom) |
288 |
+ inst_matches = vardb.match(pkg.slot_atom) |
289 |
if inst_matches: |
290 |
changelogs.extend(self.calc_changelog( |
291 |
portdb.findname(pkg_key), |
292 |
@@ -4770,7 +4768,7 @@ |
293 |
del e |
294 |
all_added = [] |
295 |
for k in self._sets: |
296 |
- if k in ("args", "world"): |
297 |
+ if k in ("args", "world") or not root_config.sets[k].world_candidate: |
298 |
continue |
299 |
s = SETPREFIX + k |
300 |
if s in world_set: |
301 |
@@ -5889,6 +5887,7 @@ |
302 |
if candidates: |
303 |
stop = False |
304 |
installed_sets += candidates |
305 |
+ installed_sets = [x for x in installed_sets if x not in root_config.setconfig.active] |
306 |
del stop, pos |
307 |
|
308 |
# we don't want to unmerge packages that are still listed in user-editable package sets |
309 |
@@ -6029,6 +6028,9 @@ |
310 |
if clean_world: |
311 |
sets["world"].cleanPackage(vartree.dbapi, y) |
312 |
emergelog(xterm_titles, " >>> unmerge success: "+y) |
313 |
+ if clean_world: |
314 |
+ for s in root_config.setconfig.active: |
315 |
+ sets["world"].remove(SETPREFIX+s) |
316 |
return 1 |
317 |
|
318 |
def chk_updated_info_files(root, infodirs, prev_mtimes, retval): |
319 |
@@ -7959,6 +7961,7 @@ |
320 |
portage.writemsg_stdout(colorize("WARN", "WARNING:") |
321 |
+ " AUTOCLEAN is disabled. This can cause serious" |
322 |
+ " problems due to overlapping packages.\n") |
323 |
+ trees[settings["ROOT"]]["vartree"].dbapi.plib_registry.pruneNonExisting() |
324 |
|
325 |
if merge_count and not (buildpkgonly or fetchonly or pretend): |
326 |
post_emerge(trees, mtimedb, retval) |
327 |
|
328 |
Modified: main/branches/prefix/pym/portage/dbapi/vartree.py |
329 |
=================================================================== |
330 |
--- main/branches/prefix/pym/portage/dbapi/vartree.py 2008-05-02 14:39:08 UTC (rev 10088) |
331 |
+++ main/branches/prefix/pym/portage/dbapi/vartree.py 2008-05-02 14:40:49 UTC (rev 10089) |
332 |
@@ -27,7 +27,7 @@ |
333 |
from portage.elog.messages import ewarn |
334 |
from portage.elog.filtering import filter_mergephases, filter_unmergephases |
335 |
|
336 |
-import os, re, sys, stat, errno, commands, copy, time |
337 |
+import os, re, sys, stat, errno, commands, copy, time, subprocess |
338 |
from itertools import izip |
339 |
|
340 |
try: |
341 |
@@ -135,38 +135,63 @@ |
342 |
def rebuild(self): |
343 |
libs = {} |
344 |
obj_properties = {} |
345 |
+ lines = [] |
346 |
for cpv in self._dbapi.cpv_all(): |
347 |
- lines = grabfile(self._dbapi.getpath(cpv, filename="NEEDED.2")) |
348 |
- for l in lines: |
349 |
- fields = l.strip("\n").split(";") |
350 |
- if len(fields) < 5: |
351 |
- print "Error", fields |
352 |
- # insufficient field length |
353 |
- continue |
354 |
- arch = fields[0] |
355 |
- obj = fields[1] |
356 |
- soname = fields[2] |
357 |
- path = fields[3].replace("${ORIGIN}", os.path.dirname(obj)).replace("$ORIGIN", os.path.dirname(obj)).split(":") |
358 |
- needed = fields[4].split(",") |
359 |
- if soname: |
360 |
- libs.setdefault(soname, {arch: {"providers": [], "consumers": []}}) |
361 |
- libs[soname].setdefault(arch, {"providers": [], "consumers": []}) |
362 |
- libs[soname][arch]["providers"].append(obj) |
363 |
- for x in needed: |
364 |
- libs.setdefault(x, {arch: {"providers": [], "consumers": []}}) |
365 |
- libs[x].setdefault(arch, {"providers": [], "consumers": []}) |
366 |
- libs[x][arch]["consumers"].append(obj) |
367 |
- obj_properties[obj] = (arch, path, needed, soname) |
368 |
+ lines += grabfile(self._dbapi.getpath(cpv, filename="NEEDED.ELF.2")) |
369 |
+ |
370 |
+ # have to call scanelf for preserved libs here as they aren't |
371 |
+ # registered in NEEDED.ELF.2 files |
372 |
+ if self._dbapi.plib_registry and self._dbapi.plib_registry.getPreservedLibs(): |
373 |
+ args = ["/usr/bin/scanelf", "-yqF", "%a;%F;%S;%r;%n"] |
374 |
+ for items in self._dbapi.plib_registry.getPreservedLibs().values(): |
375 |
+ args += items |
376 |
+ proc = subprocess.Popen(args, stdout=subprocess.PIPE) |
377 |
+ output = [l[3:] for l in proc.communicate()[0].split("\n")] |
378 |
+ lines += output |
379 |
+ |
380 |
+ for l in lines: |
381 |
+ if l.strip() == "": |
382 |
+ continue |
383 |
+ fields = l.strip("\n").split(";") |
384 |
+ if len(fields) < 5: |
385 |
+ print "Error", fields |
386 |
+ # insufficient field length |
387 |
+ continue |
388 |
+ arch = fields[0] |
389 |
+ obj = os.path.realpath(fields[1]) |
390 |
+ soname = fields[2] |
391 |
+ path = fields[3].replace("${ORIGIN}", os.path.dirname(obj)).replace("$ORIGIN", os.path.dirname(obj)).split(":") |
392 |
+ needed = fields[4].split(",") |
393 |
+ if soname: |
394 |
+ libs.setdefault(soname, {arch: {"providers": [], "consumers": []}}) |
395 |
+ libs[soname].setdefault(arch, {"providers": [], "consumers": []}) |
396 |
+ libs[soname][arch]["providers"].append(obj) |
397 |
+ for x in needed: |
398 |
+ libs.setdefault(x, {arch: {"providers": [], "consumers": []}}) |
399 |
+ libs[x].setdefault(arch, {"providers": [], "consumers": []}) |
400 |
+ libs[x][arch]["consumers"].append(obj) |
401 |
+ obj_properties[obj] = (arch, needed, path, soname) |
402 |
|
403 |
self._libs = libs |
404 |
self._obj_properties = obj_properties |
405 |
+ |
406 |
+ def listLibraryObjects(self): |
407 |
+ rValue = [] |
408 |
+ if not self._libs: |
409 |
+ self.rebuild() |
410 |
+ for soname in self._libs: |
411 |
+ for arch in self._libs[soname]: |
412 |
+ rValue.extend(self._libs[soname][arch]["providers"]) |
413 |
+ return rValue |
414 |
|
415 |
def findProviders(self, obj): |
416 |
+ if not self._libs: |
417 |
+ self.rebuild() |
418 |
obj = os.path.realpath(obj) |
419 |
rValue = {} |
420 |
if obj not in self._obj_properties: |
421 |
raise KeyError("%s not in object list" % obj) |
422 |
- arch, path, needed, soname = self._obj_properties[obj] |
423 |
+ arch, needed, path, soname = self._obj_properties[obj] |
424 |
path.extend(self._defpath) |
425 |
path = [os.path.realpath(x) for x in path] |
426 |
for x in needed: |
427 |
@@ -181,13 +206,15 @@ |
428 |
return rValue |
429 |
|
430 |
def findConsumers(self, obj): |
431 |
+ if not self._libs: |
432 |
+ self.rebuild() |
433 |
obj = os.path.realpath(obj) |
434 |
rValue = set() |
435 |
for soname in self._libs: |
436 |
for arch in self._libs[soname]: |
437 |
if obj in self._libs[soname][arch]["providers"]: |
438 |
for x in self._libs[soname][arch]["consumers"]: |
439 |
- path = self._obj_properties[x][1] |
440 |
+ path = self._obj_properties[x][2] |
441 |
path = [os.path.realpath(y) for y in path+self._defpath] |
442 |
if soname[0] == os.sep and os.path.realpath(soname) == os.path.realpath(obj): |
443 |
rValue.add(x) |
444 |
@@ -293,7 +320,6 @@ |
445 |
self._counter_path = os.path.join(root, |
446 |
CACHE_PATH.lstrip(os.path.sep), "counter") |
447 |
|
448 |
- self.libmap = LibraryPackageMap(os.path.join(self.root, CACHE_PATH.lstrip(os.sep), "library_consumers"), self) |
449 |
try: |
450 |
self.plib_registry = PreservedLibsRegistry( |
451 |
os.path.join(self.root, PRIVATE_PATH, "preserved_libs_registry")) |
452 |
@@ -301,6 +327,8 @@ |
453 |
# apparently this user isn't allowed to access PRIVATE_PATH |
454 |
self.plib_registry = None |
455 |
|
456 |
+ self.linkmap = LinkageMap(self) |
457 |
+ |
458 |
def getpath(self, mykey, filename=None): |
459 |
rValue = os.path.join(self.root, VDB_PATH, mykey) |
460 |
if filename != None: |
461 |
@@ -1271,31 +1299,35 @@ |
462 |
return retval |
463 |
|
464 |
# regenerate reverse NEEDED map |
465 |
- self.vartree.dbapi.libmap.update() |
466 |
+ self.vartree.dbapi.linkmap.rebuild() |
467 |
|
468 |
# remove preserved libraries that don't have any consumers left |
469 |
# FIXME: this code is quite ugly and can likely be optimized in several ways |
470 |
plib_dict = plib_registry.getPreservedLibs() |
471 |
for cpv in plib_dict: |
472 |
- keeplist = [] |
473 |
plib_dict[cpv].sort() |
474 |
+ # for the loop below to work correctly, we need all |
475 |
+ # symlinks to come before the actual files, such that |
476 |
+ # the recorded symlinks (sonames) will be resolved into |
477 |
+ # their real target before the object is found not to be |
478 |
+ # in the reverse NEEDED map |
479 |
+ def symlink_compare(x, y): |
480 |
+ if os.path.islink(x): |
481 |
+ if os.path.islink(y): |
482 |
+ return 0 |
483 |
+ else: |
484 |
+ return -1 |
485 |
+ elif os.path.islink(y): |
486 |
+ return 1 |
487 |
+ else: |
488 |
+ return 0 |
489 |
+ |
490 |
+ plib_dict[cpv].sort(symlink_compare) |
491 |
for f in plib_dict[cpv]: |
492 |
- if not os.path.exists(f) or os.path.realpath(f) in keeplist: |
493 |
+ if not os.path.exists(f): |
494 |
continue |
495 |
unlink_list = [] |
496 |
- while os.path.islink(f): |
497 |
- if os.path.basename(f) in self.vartree.dbapi.libmap.get(): |
498 |
- unlink_list = [] |
499 |
- keeplist.append(os.path.realpath(f)) |
500 |
- break |
501 |
- else: |
502 |
- unlink_list.append(f) |
503 |
- # only follow symlinks if the target is also a preserved lib object |
504 |
- if os.readlink(f) in plib_dict[cpv]: |
505 |
- f = os.readlink(f) |
506 |
- else: |
507 |
- break |
508 |
- if not os.path.islink(f) and not os.path.basename(f) in self.vartree.dbapi.libmap.get(): |
509 |
+ if not self.vartree.dbapi.linkmap.findConsumers(f): |
510 |
unlink_list.append(f) |
511 |
for obj in unlink_list: |
512 |
try: |
513 |
@@ -1682,22 +1714,27 @@ |
514 |
|
515 |
def _preserve_libs(self, srcroot, destroot, mycontents, counter): |
516 |
# read global reverse NEEDED map |
517 |
- libmap = self.vartree.dbapi.libmap.get() |
518 |
+ linkmap = self.vartree.dbapi.linkmap |
519 |
+ linkmap.rebuild() |
520 |
+ liblist = linkmap.listLibraryObjects() |
521 |
|
522 |
# get list of libraries from old package instance |
523 |
old_contents = self._installed_instance.getcontents().keys() |
524 |
- old_libs = set([os.path.basename(x) for x in old_contents]).intersection(libmap) |
525 |
+ old_libs = set(old_contents).intersection(liblist) |
526 |
|
527 |
# get list of libraries from new package instance |
528 |
- mylibs = set([os.path.basename(x) for x in mycontents]).intersection(libmap) |
529 |
+ mylibs = set(mycontents).intersection(liblist) |
530 |
|
531 |
# check which libs are present in the old, but not the new package instance |
532 |
- preserve_libs = old_libs.difference(mylibs) |
533 |
+ candidates = old_libs.difference(mylibs) |
534 |
+ for x in old_contents: |
535 |
+ if os.path.islink(x) and os.path.realpath(x) in candidates: |
536 |
+ candidates.add(x) |
537 |
|
538 |
# ignore any libs that are only internally used by the package |
539 |
def has_external_consumers(lib, contents, otherlibs): |
540 |
- consumers = set(libmap[lib]) |
541 |
- contents_without_libs = [x for x in contents if not os.path.basename(x) in otherlibs] |
542 |
+ consumers = linkmap.findConsumers(lib) |
543 |
+ contents_without_libs = [x for x in contents if x not in otherlibs] |
544 |
|
545 |
# just used by objects that will be autocleaned |
546 |
if len(consumers.difference(contents_without_libs)) == 0: |
547 |
@@ -1714,23 +1751,34 @@ |
548 |
else: |
549 |
return True |
550 |
|
551 |
- for lib in list(preserve_libs): |
552 |
- if not has_external_consumers(lib, old_contents, preserve_libs): |
553 |
- preserve_libs.remove(lib) |
554 |
- # only preserve the lib if there is no other copy in the search path |
555 |
- for path in getlibpaths(): |
556 |
- fullname = os.path.join(path, lib) |
557 |
- if fullname not in old_contents and os.path.exists(fullname) and lib in preserve_libs: |
558 |
- preserve_libs.remove(lib) |
559 |
- |
560 |
- # get the real paths for the libs |
561 |
- preserve_paths = [x for x in old_contents if os.path.basename(x) in preserve_libs] |
562 |
- del old_contents, old_libs, mylibs, preserve_libs |
563 |
- |
564 |
+ for lib in list(candidates): |
565 |
+ if not has_external_consumers(lib, old_contents, candidates): |
566 |
+ candidates.remove(lib) |
567 |
+ # only preserve the lib if there is no other copy to use for each consumer |
568 |
+ keep = False |
569 |
+ for c in linkmap.findConsumers(lib): |
570 |
+ localkeep = True |
571 |
+ providers = linkmap.findProviders(c) |
572 |
+ for soname in providers: |
573 |
+ if lib in providers[soname]: |
574 |
+ for p in providers[soname]: |
575 |
+ if p not in candidates: |
576 |
+ localkeep = False |
577 |
+ break |
578 |
+ break |
579 |
+ if localkeep: |
580 |
+ keep = True |
581 |
+ |
582 |
+ del mylibs, mycontents, old_contents, liblist |
583 |
+ |
584 |
# inject files that should be preserved into our image dir |
585 |
import shutil |
586 |
missing_paths = [] |
587 |
- for x in preserve_paths: |
588 |
+ for x in candidates: |
589 |
+ # skip existing files so the 'new' libs aren't overwritten |
590 |
+ if os.path.exists(os.path.join(srcroot, x.lstrip(os.sep))): |
591 |
+ missing_paths.append(x) |
592 |
+ continue |
593 |
print "injecting %s into %s" % (x, srcroot) |
594 |
if not os.path.exists(os.path.join(destroot, x.lstrip(os.sep))): |
595 |
print "%s does not exist so can't be preserved" % x |
596 |
@@ -1748,14 +1796,14 @@ |
597 |
os.symlink(linktarget, os.path.join(srcroot, x.lstrip(os.sep))) |
598 |
if linktarget[0] != os.sep: |
599 |
linktarget = os.path.join(os.path.dirname(x), linktarget) |
600 |
- preserve_paths.append(linktarget) |
601 |
+ candidates.add(linktarget) |
602 |
else: |
603 |
shutil.copy2(os.path.join(destroot, x.lstrip(os.sep)), |
604 |
os.path.join(srcroot, x.lstrip(os.sep))) |
605 |
|
606 |
- preserve_paths = [x for x in preserve_paths if x not in missing_paths] |
607 |
+ preserve_paths = [x for x in candidates if x not in missing_paths] |
608 |
|
609 |
- del missing_paths |
610 |
+ del missing_paths, candidates |
611 |
|
612 |
# keep track of the libs we preserved |
613 |
self.vartree.dbapi.plib_registry.register(self.mycpv, self.settings["SLOT"], counter, preserve_paths) |
614 |
@@ -2293,7 +2341,7 @@ |
615 |
del conf_mem_file |
616 |
|
617 |
# regenerate reverse NEEDED map |
618 |
- self.vartree.dbapi.libmap.update() |
619 |
+ self.vartree.dbapi.linkmap.rebuild() |
620 |
|
621 |
#do postinst script |
622 |
self.settings["PORTAGE_UPDATE_ENV"] = \ |
623 |
|
624 |
Modified: main/branches/prefix/pym/portage/sets/__init__.py |
625 |
=================================================================== |
626 |
--- main/branches/prefix/pym/portage/sets/__init__.py 2008-05-02 14:39:08 UTC (rev 10088) |
627 |
+++ main/branches/prefix/pym/portage/sets/__init__.py 2008-05-02 14:40:49 UTC (rev 10089) |
628 |
@@ -32,7 +32,6 @@ |
629 |
self.settings = settings |
630 |
self._parsed = False |
631 |
self.active = [] |
632 |
- self.aliases = {} |
633 |
|
634 |
def _parse(self): |
635 |
if self._parsed: |
636 |
@@ -58,11 +57,19 @@ |
637 |
# create single or multiple instances of the given class depending on configuration |
638 |
if self.has_option(sname, "multiset") and self.getboolean(sname, "multiset"): |
639 |
if hasattr(setclass, "multiBuilder"): |
640 |
+ newsets = {} |
641 |
try: |
642 |
- self.psets.update(setclass.multiBuilder(optdict, self.settings, self.trees)) |
643 |
+ newsets = setclass.multiBuilder(optdict, self.settings, self.trees) |
644 |
except SetConfigError, e: |
645 |
self.errors.append("Configuration error in section '%s': %s" % (sname, str(e))) |
646 |
continue |
647 |
+ for x in newsets: |
648 |
+ if x in self.psets: |
649 |
+ self.errors.append("Redefinition of set '%s' (sections: '%s', '%s')" % (setname, self.psets[setname].creator, sname)) |
650 |
+ newsets[x].creator = sname |
651 |
+ if self.has_option(sname, "world-candidate") and not self.getboolean(sname, "world-candidate"): |
652 |
+ newsets[x].world_candidate = False |
653 |
+ self.psets.update(newsets) |
654 |
else: |
655 |
self.errors.append("Section '%s' is configured as multiset, but '%s' doesn't support that configuration" % (sname, classname)) |
656 |
continue |
657 |
@@ -71,9 +78,14 @@ |
658 |
setname = self.get(sname, "name") |
659 |
except NoOptionError: |
660 |
setname = sname |
661 |
+ if setname in self.psets: |
662 |
+ self.errors.append("Redefinition of set '%s' (sections: '%s', '%s')" % (setname, self.psets[setname].creator, sname)) |
663 |
if hasattr(setclass, "singleBuilder"): |
664 |
try: |
665 |
self.psets[setname] = setclass.singleBuilder(optdict, self.settings, self.trees) |
666 |
+ self.psets[setname].creator = sname |
667 |
+ if self.has_option(sname, "world-candidate") and not self.getboolean(sname, "world-candidate"): |
668 |
+ self.psets[setname].world_candidate = False |
669 |
except SetConfigError, e: |
670 |
self.errors.append("Configuration error in section '%s': %s" % (sname, str(e))) |
671 |
continue |
672 |
|
673 |
Modified: main/branches/prefix/pym/portage/sets/base.py |
674 |
=================================================================== |
675 |
--- main/branches/prefix/pym/portage/sets/base.py 2008-05-02 14:39:08 UTC (rev 10088) |
676 |
+++ main/branches/prefix/pym/portage/sets/base.py 2008-05-02 14:40:49 UTC (rev 10089) |
677 |
@@ -24,6 +24,7 @@ |
678 |
self._loading = False |
679 |
self.errors = [] |
680 |
self._nonatoms = set() |
681 |
+ self.world_candidate = True |
682 |
|
683 |
def __contains__(self, atom): |
684 |
self._load() |
685 |
@@ -182,6 +183,7 @@ |
686 |
def remove(self, atom): |
687 |
self._load() |
688 |
self._atoms.discard(atom) |
689 |
+ self._nonatoms.discard(atom) |
690 |
self._updateAtomMap() |
691 |
self.write() |
692 |
|
693 |
|
694 |
Modified: main/branches/prefix/pym/portage/sets/dbapi.py |
695 |
=================================================================== |
696 |
--- main/branches/prefix/pym/portage/sets/dbapi.py 2008-05-02 14:39:08 UTC (rev 10088) |
697 |
+++ main/branches/prefix/pym/portage/sets/dbapi.py 2008-05-02 14:40:49 UTC (rev 10089) |
698 |
@@ -2,14 +2,10 @@ |
699 |
# Distributed under the terms of the GNU General Public License v2 |
700 |
# $Id$ |
701 |
|
702 |
-from portage.versions import catsplit, catpkgsplit |
703 |
+from portage.versions import catsplit |
704 |
from portage.sets.base import PackageSet |
705 |
from portage.sets import SetConfigError, get_boolean |
706 |
-from portage.dbapi.vartree import dblink |
707 |
-from portage.util import grabfile |
708 |
|
709 |
-import os |
710 |
- |
711 |
__all__ = ["CategorySet", "EverythingSet"] |
712 |
|
713 |
class EverythingSet(PackageSet): |
714 |
@@ -108,71 +104,3 @@ |
715 |
return rValue |
716 |
multiBuilder = classmethod(multiBuilder) |
717 |
|
718 |
-class LibraryConsumerSet(PackageSet): |
719 |
- _operations = ["merge", "unmerge"] |
720 |
- |
721 |
- def __init__(self, vardbapi, debug=False): |
722 |
- super(LibraryConsumerSet, self).__init__() |
723 |
- self.dbapi = vardbapi |
724 |
- self.debug = debug |
725 |
- |
726 |
- def mapPathsToAtoms(self, paths): |
727 |
- rValue = set() |
728 |
- for cpv in self.dbapi.cpv_all(): |
729 |
- mysplit = catsplit(cpv) |
730 |
- link = dblink(mysplit[0], mysplit[1], myroot=self.dbapi.root, \ |
731 |
- mysettings=self.dbapi.settings, treetype='vartree', \ |
732 |
- vartree=self.dbapi.vartree) |
733 |
- if paths.intersection(link.getcontents()): |
734 |
- cat, pn = catpkgsplit(cpv)[:2] |
735 |
- slot = self.dbapi.aux_get(cpv, ["SLOT"])[0] |
736 |
- rValue.add("%s/%s:%s" % (cat, pn, slot)) |
737 |
- return rValue |
738 |
- |
739 |
- |
740 |
-class PreservedLibraryConsumerSet(LibraryConsumerSet): |
741 |
- def load(self): |
742 |
- reg = self.dbapi.plib_registry |
743 |
- libmap = self.dbapi.libmap.get() |
744 |
- consumers = set() |
745 |
- if reg: |
746 |
- for libs in reg.getPreservedLibs().values(): |
747 |
- for lib in libs: |
748 |
- paths = libmap.get(os.path.basename(lib), []) |
749 |
- consumers.update(paths) |
750 |
- else: |
751 |
- return |
752 |
- if not consumers: |
753 |
- return |
754 |
- self._setAtoms(self.mapPathsToAtoms(consumers)) |
755 |
- |
756 |
- def singleBuilder(cls, options, settings, trees): |
757 |
- return PreservedLibraryConsumerSet(trees["vartree"].dbapi) |
758 |
- singleBuilder = classmethod(singleBuilder) |
759 |
- |
760 |
-class MissingLibraryConsumerSet(LibraryConsumerSet): |
761 |
- _operations = ["merge", "unmerge"] |
762 |
- |
763 |
- def load(self): |
764 |
- atoms = set() |
765 |
- consumers = set() |
766 |
- for lib in self.dbapi.libmap.get(): |
767 |
- found=False |
768 |
- for searchdir in grabfile(os.path.join(os.sep, self.dbapi.root, "etc/ld.so.conf")): |
769 |
- if os.path.exists(os.path.join(searchdir, lib)): |
770 |
- found=True |
771 |
- break |
772 |
- if not found: |
773 |
- print "missing library: %s" % lib |
774 |
- print "consumers:" |
775 |
- for x in self.dbapi.libmap.get()[lib]: |
776 |
- print " ", x |
777 |
- consumers.update(self.dbapi.libmap.get()[lib]) |
778 |
- if not consumers: |
779 |
- return |
780 |
- self._setAtoms(self.mapPathsToAtoms(consumers)) |
781 |
- |
782 |
- def singleBuilder(cls, options, settings, trees): |
783 |
- debug = get_boolean(options, "debug", False) |
784 |
- return MissingLibraryConsumerSet(trees["vartree"].dbapi, debug=debug) |
785 |
- singleBuilder = classmethod(singleBuilder) |
786 |
|
787 |
Modified: main/branches/prefix/pym/portage/sets/files.py |
788 |
=================================================================== |
789 |
--- main/branches/prefix/pym/portage/sets/files.py 2008-05-02 14:39:08 UTC (rev 10088) |
790 |
+++ main/branches/prefix/pym/portage/sets/files.py 2008-05-02 14:40:49 UTC (rev 10089) |
791 |
@@ -107,7 +107,7 @@ |
792 |
def multiBuilder(self, options, settings, trees): |
793 |
rValue = {} |
794 |
directory = options.get("directory", os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH.lstrip(os.sep), "sets")) |
795 |
- name_pattern = options.get("name_pattern", "sets/${name}") |
796 |
+ name_pattern = options.get("name_pattern", "${name}") |
797 |
if not "$name" in name_pattern and not "${name}" in name_pattern: |
798 |
raise SetConfigError("name_pattern doesn't include ${name} placeholder") |
799 |
greedy = get_boolean(options, "greedy", False) |
800 |
|
801 |
Copied: main/branches/prefix/pym/portage/sets/libs.py (from rev 10086, main/trunk/pym/portage/sets/libs.py) |
802 |
=================================================================== |
803 |
--- main/branches/prefix/pym/portage/sets/libs.py (rev 0) |
804 |
+++ main/branches/prefix/pym/portage/sets/libs.py 2008-05-02 14:40:49 UTC (rev 10089) |
805 |
@@ -0,0 +1,50 @@ |
806 |
+# Copyright 2007 Gentoo Foundation |
807 |
+# Distributed under the terms of the GNU General Public License v2 |
808 |
+# $Id$ |
809 |
+ |
810 |
+from portage.sets.base import PackageSet |
811 |
+from portage.dbapi.vartree import dblink |
812 |
+from portage.versions import catsplit, catpkgsplit |
813 |
+ |
814 |
+import os |
815 |
+ |
816 |
+class LibraryConsumerSet(PackageSet): |
817 |
+ _operations = ["merge", "unmerge"] |
818 |
+ |
819 |
+ def __init__(self, vardbapi, debug=False): |
820 |
+ super(LibraryConsumerSet, self).__init__() |
821 |
+ self.dbapi = vardbapi |
822 |
+ self.debug = debug |
823 |
+ |
824 |
+ def mapPathsToAtoms(self, paths): |
825 |
+ rValue = set() |
826 |
+ for cpv in self.dbapi.cpv_all(): |
827 |
+ mysplit = catsplit(cpv) |
828 |
+ link = dblink(mysplit[0], mysplit[1], myroot=self.dbapi.root, \ |
829 |
+ mysettings=self.dbapi.settings, treetype='vartree', \ |
830 |
+ vartree=self.dbapi.vartree) |
831 |
+ if paths.intersection(link.getcontents()): |
832 |
+ cat, pn = catpkgsplit(cpv)[:2] |
833 |
+ slot = self.dbapi.aux_get(cpv, ["SLOT"])[0] |
834 |
+ rValue.add("%s/%s:%s" % (cat, pn, slot)) |
835 |
+ return rValue |
836 |
+ |
837 |
+ |
838 |
+class PreservedLibraryConsumerSet(LibraryConsumerSet): |
839 |
+ def load(self): |
840 |
+ reg = self.dbapi.plib_registry |
841 |
+ consumers = set() |
842 |
+ if reg: |
843 |
+ for libs in reg.getPreservedLibs().values(): |
844 |
+ for lib in libs: |
845 |
+ #print lib, self.dbapi.linkmap.findConsumers(lib) |
846 |
+ consumers.update(self.dbapi.linkmap.findConsumers(lib)) |
847 |
+ else: |
848 |
+ return |
849 |
+ if not consumers: |
850 |
+ return |
851 |
+ self._setAtoms(self.mapPathsToAtoms(consumers)) |
852 |
+ |
853 |
+ def singleBuilder(cls, options, settings, trees): |
854 |
+ return PreservedLibraryConsumerSet(trees["vartree"].dbapi) |
855 |
+ singleBuilder = classmethod(singleBuilder) |
856 |
|
857 |
-- |
858 |
gentoo-commits@l.g.o mailing list |