1 |
From: Sergei Trofimovich <siarheit@××××××.com> |
2 |
|
3 |
A few links discussing what can go wrong with slot operator under '||': |
4 |
https://archives.gentoo.org/gentoo-dev/message/81a4e1a1f5767e20009628ecd33da8d4 |
5 |
https://archives.gentoo.org/gentoo-dev/message/66ff016a055e57b6027abcd36734e0e3 |
6 |
|
7 |
The main problem here is how vdb gets updated when you have a dependency of style: |
8 |
RDEPEND="|| ( foo:= bar:= )" |
9 |
depending on what you have installed in system: only 'foo'/'bar' or both 'foo' and 'bar'. |
10 |
|
11 |
I'm about to add actual test for some examples to gen-b0rk. |
12 |
|
13 |
New repoman complains on them as follows: |
14 |
|
15 |
RDEPEND="|| ( =not-broken/pkg1-subslot-0:= =not-broken/pkg1-subslot-1:0= )" |
16 |
|
17 |
Yields: |
18 |
|
19 |
dependency.badslotop [fatal] 2 |
20 |
ebuild-test/RDEPEND-any-of-slotop/RDEPEND-any-of-slotop-0.ebuild: RDEPEND: '=not-broken/pkg1-subslot-0:=' uses ':=' slot operator under '||' dep clause. |
21 |
ebuild-test/RDEPEND-any-of-slotop/RDEPEND-any-of-slotop-0.ebuild: RDEPEND: '=not-broken/pkg1-subslot-1:0=' uses ':=' slot operator under '||' dep clause. |
22 |
|
23 |
CC: dolsen@g.o |
24 |
CC: qa@g.o |
25 |
CC: mgorny@g.o |
26 |
Signed-off-by: Sergei Trofimovich <siarheit@××××××.com> |
27 |
--- |
28 |
V4: forbid only ':=' style slot operator. Zac pointed out ':*' is fine here. |
29 |
V3: unbaked tree traversal back to _traverse_tree, moved dependency parser out |
30 |
to check_slotop() helper |
31 |
V2: made check_slotop function local, baked tree traversal in it |
32 |
.../repoman/modules/scan/depend/_depend_checks.py | 45 ++++++++++++++++++++++ |
33 |
repoman/pym/repoman/qa_data.py | 2 + |
34 |
2 files changed, 47 insertions(+) |
35 |
|
36 |
diff --git a/repoman/pym/repoman/modules/scan/depend/_depend_checks.py b/repoman/pym/repoman/modules/scan/depend/_depend_checks.py |
37 |
index 4e1d216..3f6c93e 100644 |
38 |
--- a/repoman/pym/repoman/modules/scan/depend/_depend_checks.py |
39 |
+++ b/repoman/pym/repoman/modules/scan/depend/_depend_checks.py |
40 |
@@ -3,11 +3,52 @@ |
41 |
|
42 |
from _emerge.Package import Package |
43 |
|
44 |
+from portage.dep import Atom |
45 |
+ |
46 |
from repoman.check_missingslot import check_missingslot |
47 |
# import our initialized portage instance |
48 |
from repoman._portage import portage |
49 |
from repoman.qa_data import suspect_virtual, suspect_rdepend |
50 |
|
51 |
+def check_slotop(depstr, is_valid_flag, badsyntax, mytype, |
52 |
+ qatracker, relative_path): |
53 |
+ '''Checks if RDEPEND uses ':=' slot operator |
54 |
+ in '||' style dependencies.''' |
55 |
+ |
56 |
+ try: |
57 |
+ # to find use of ':=' in '||' we preserve |
58 |
+ # tree structure of dependencies |
59 |
+ my_dep_tree = portage.dep.use_reduce( |
60 |
+ depstr, |
61 |
+ flat=False, |
62 |
+ matchall=1, |
63 |
+ is_valid_flag=is_valid_flag, |
64 |
+ opconvert=True, |
65 |
+ token_class=portage.dep.Atom) |
66 |
+ except portage.exception.InvalidDependString as e: |
67 |
+ my_dep_tree = None |
68 |
+ badsyntax.append(str(e)) |
69 |
+ |
70 |
+ def _traverse_tree(dep_tree, in_any_of): |
71 |
+ # leaf |
72 |
+ if isinstance(dep_tree, Atom): |
73 |
+ atom = dep_tree |
74 |
+ if in_any_of and atom.slot_operator == '=': |
75 |
+ qatracker.add_error("dependency.badslotop", |
76 |
+ "%s: %s: '%s' uses ':=' slot operator under '||' dep clause." % |
77 |
+ (relative_path, mytype, atom)) |
78 |
+ |
79 |
+ # branches |
80 |
+ if isinstance(dep_tree, list): |
81 |
+ if len(dep_tree) == 0: |
82 |
+ return |
83 |
+ # entering any-of |
84 |
+ if dep_tree[0] == '||': |
85 |
+ _traverse_tree(dep_tree[1:], in_any_of=True) |
86 |
+ else: |
87 |
+ for branch in dep_tree: |
88 |
+ _traverse_tree(branch, in_any_of=in_any_of) |
89 |
+ _traverse_tree(my_dep_tree, False) |
90 |
|
91 |
def _depend_checks(ebuild, pkg, portdb, qatracker, repo_metadata): |
92 |
'''Checks the ebuild dependencies for errors |
93 |
@@ -117,6 +158,10 @@ def _depend_checks(ebuild, pkg, portdb, qatracker, repo_metadata): |
94 |
|
95 |
type_list.extend([mytype] * (len(badsyntax) - len(type_list))) |
96 |
|
97 |
+ if runtime: |
98 |
+ check_slotop(mydepstr, pkg.iuse.is_valid_flag, |
99 |
+ badsyntax, mytype, qatracker, ebuild.relative_path) |
100 |
+ |
101 |
for m, b in zip(type_list, badsyntax): |
102 |
if m.endswith("DEPEND"): |
103 |
qacat = "dependency.syntax" |
104 |
diff --git a/repoman/pym/repoman/qa_data.py b/repoman/pym/repoman/qa_data.py |
105 |
index b9475e8..48ab389 100644 |
106 |
--- a/repoman/pym/repoman/qa_data.py |
107 |
+++ b/repoman/pym/repoman/qa_data.py |
108 |
@@ -58,6 +58,8 @@ qahelp = { |
109 |
"Ebuild has a dependency that refers to an unknown package" |
110 |
" (which may be valid if it is a blocker for a renamed/removed package," |
111 |
" or is an alternative choice provided by an overlay)"), |
112 |
+ "dependency.badslotop": ( |
113 |
+ "RDEPEND contains ':=' slot operator under '||' dependency."), |
114 |
"file.executable": ( |
115 |
"Ebuilds, digests, metadata.xml, Manifest, and ChangeLog do not need" |
116 |
" the executable bit"), |
117 |
-- |
118 |
2.9.0 |