Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r10089 - in main/branches/prefix: bin cnf doc/config pym/_emerge pym/portage/dbapi pym/portage/sets
Date: Fri, 02 May 2008 14:40:55
Message-Id: E1JrwRP-0003f8-6f@stork.gentoo.org
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