1 |
The @changed-deps set tries to compare RDEPEND and PDEPEND entries of |
2 |
installed packages with ebuild counterparts, and pulls the ebuild |
3 |
whenever the two are not in sync. This could be used, for example, to |
4 |
clean up the system after disabling --dynamic-deps. |
5 |
--- |
6 |
cnf/sets/portage.conf | 5 +++ |
7 |
pym/portage/_sets/dbapi.py | 81 ++++++++++++++++++++++++++++++++++++++++++++-- |
8 |
2 files changed, 84 insertions(+), 2 deletions(-) |
9 |
|
10 |
diff --git a/cnf/sets/portage.conf b/cnf/sets/portage.conf |
11 |
index b73afb1..fd2c387 100644 |
12 |
--- a/cnf/sets/portage.conf |
13 |
+++ b/cnf/sets/portage.conf |
14 |
@@ -84,3 +84,8 @@ class = portage.sets.dbapi.UnavailableSet |
15 |
# are not available. |
16 |
[unavailable-binaries] |
17 |
class = portage.sets.dbapi.UnavailableBinaries |
18 |
+ |
19 |
+# Installed packages for which vdb *DEPEND entries are outdated compared |
20 |
+# to the matching portdb entry. |
21 |
+[changed-deps] |
22 |
+class = portage.sets.dbapi.ChangedDepsSet |
23 |
diff --git a/pym/portage/_sets/dbapi.py b/pym/portage/_sets/dbapi.py |
24 |
index 817bcd7..299cb81 100644 |
25 |
--- a/pym/portage/_sets/dbapi.py |
26 |
+++ b/pym/portage/_sets/dbapi.py |
27 |
@@ -3,17 +3,19 @@ |
28 |
|
29 |
from __future__ import division |
30 |
|
31 |
+import re |
32 |
import time |
33 |
|
34 |
from portage import os |
35 |
from portage.versions import best, catsplit, vercmp |
36 |
-from portage.dep import Atom |
37 |
+from portage.dep import Atom, use_reduce |
38 |
+from portage.exception import InvalidAtom |
39 |
from portage.localization import _ |
40 |
from portage._sets.base import PackageSet |
41 |
from portage._sets import SetConfigError, get_boolean |
42 |
import portage |
43 |
|
44 |
-__all__ = ["CategorySet", "DowngradeSet", |
45 |
+__all__ = ["CategorySet", "ChangedDepsSet", "DowngradeSet", |
46 |
"EverythingSet", "OwnerSet", "VariableSet"] |
47 |
|
48 |
class EverythingSet(PackageSet): |
49 |
@@ -458,3 +460,78 @@ class RebuiltBinaries(EverythingSet): |
50 |
bindb=trees["bintree"].dbapi) |
51 |
|
52 |
singleBuilder = classmethod(singleBuilder) |
53 |
+ |
54 |
+class ChangedDepsSet(PackageSet): |
55 |
+ |
56 |
+ _operations = ["merge", "unmerge"] |
57 |
+ |
58 |
+ description = "Package set which contains all installed " + \ |
59 |
+ "packages for which the vdb *DEPEND entries are outdated " + \ |
60 |
+ "compared to corresponding portdb entries." |
61 |
+ |
62 |
+ def __init__(self, portdb=None, vardb=None): |
63 |
+ super(ChangedDepsSet, self).__init__() |
64 |
+ self._portdb = portdb |
65 |
+ self._vardb = vardb |
66 |
+ |
67 |
+ def load(self): |
68 |
+ depvars = ('RDEPEND', 'PDEPEND') |
69 |
+ |
70 |
+ # regexp used to match atoms using subslot operator := |
71 |
+ subslot_repl_re = re.compile(r':[^[]*=') |
72 |
+ |
73 |
+ atoms = [] |
74 |
+ for cpv in self._vardb.cpv_all(): |
75 |
+ # no ebuild, no update :). |
76 |
+ if not self._portdb.cpv_exists(cpv): |
77 |
+ continue |
78 |
+ |
79 |
+ # USE flags used to build the ebuild and EAPI |
80 |
+ # (needed for Atom & use_reduce()) |
81 |
+ use, eapi = self._vardb.aux_get(cpv, ('USE', 'EAPI')) |
82 |
+ usel = use.split() |
83 |
+ |
84 |
+ # function used to recursively process atoms in nested lists. |
85 |
+ def clean_subslots(depatom, usel=None): |
86 |
+ if isinstance(depatom, list): |
87 |
+ # process the nested list. |
88 |
+ return [clean_subslots(x, usel) for x in depatom] |
89 |
+ else: |
90 |
+ try: |
91 |
+ # this can be either an atom or some special operator. |
92 |
+ # in the latter case, we get InvalidAtom and pass it as-is. |
93 |
+ a = Atom(depatom) |
94 |
+ except InvalidAtom: |
95 |
+ return depatom |
96 |
+ else: |
97 |
+ # if we're processing portdb, we need to evaluate USE flag |
98 |
+ # dependency conditionals to make them match vdb. this |
99 |
+ # requires passing the list of USE flags, so we reuse it |
100 |
+ # as conditional for the operation as well. |
101 |
+ if usel is not None: |
102 |
+ a = a.evaluate_conditionals(usel) |
103 |
+ |
104 |
+ # replace slot operator := dependencies with plain := |
105 |
+ # since we can't properly compare expanded slots |
106 |
+ # in vardb to abstract slots in portdb. |
107 |
+ return subslot_repl_re.sub(':=', a) |
108 |
+ |
109 |
+ # get all *DEPEND variables from vdb & portdb and compare them. |
110 |
+ # we need to do some cleaning up & expansion to make matching |
111 |
+ # meaningful since vdb dependencies are conditional-free. |
112 |
+ vdbvars = [clean_subslots(use_reduce(x, uselist=usel, eapi=eapi)) |
113 |
+ for x in self._vardb.aux_get(cpv, depvars)] |
114 |
+ pdbvars = [clean_subslots(use_reduce(x, uselist=usel, eapi=eapi), usel) |
115 |
+ for x in self._portdb.aux_get(cpv, depvars)] |
116 |
+ |
117 |
+ # if dependencies don't match, trigger the rebuild. |
118 |
+ if vdbvars != pdbvars: |
119 |
+ atoms.append('=%s' % cpv) |
120 |
+ |
121 |
+ self._setAtoms(atoms) |
122 |
+ |
123 |
+ def singleBuilder(cls, options, settings, trees): |
124 |
+ return cls(portdb=trees["porttree"].dbapi, |
125 |
+ vardb=trees["vartree"].dbapi) |
126 |
+ |
127 |
+ singleBuilder = classmethod(singleBuilder) |
128 |
-- |
129 |
2.0.4 |