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