1 |
commit: 7c9f1da09e6660ba6f5eb4c677412c5c7c601c34 |
2 |
Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Jan 20 08:59:38 2023 +0000 |
4 |
Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri Jan 20 08:59:38 2023 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=7c9f1da0 |
7 |
|
8 |
domain: support `-*` in use as previous removal |
9 |
|
10 |
Add support for `-*` and `USE_EXPAND: -*` syntax. Allow this syntax, and |
11 |
update incremental computation of resulting use combination. |
12 |
|
13 |
Resolves: https://github.com/pkgcore/pkgcore/issues/393 |
14 |
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> |
15 |
|
16 |
src/pkgcore/ebuild/domain.py | 40 ++++++++++++++++++++++++---------------- |
17 |
src/pkgcore/ebuild/misc.py | 8 +++++++- |
18 |
tests/ebuild/test_domain.py | 41 ++++++++++++++++++++++++++++++++--------- |
19 |
3 files changed, 63 insertions(+), 26 deletions(-) |
20 |
|
21 |
diff --git a/src/pkgcore/ebuild/domain.py b/src/pkgcore/ebuild/domain.py |
22 |
index 0dba49d5d..fd5b39fc3 100644 |
23 |
--- a/src/pkgcore/ebuild/domain.py |
24 |
+++ b/src/pkgcore/ebuild/domain.py |
25 |
@@ -69,11 +69,11 @@ def package_masks(iterable): |
26 |
|
27 |
def restriction_payload_splitter(iterable, post_process=lambda x: x): |
28 |
for line, lineno, path in iterable: |
29 |
- v = line.split() |
30 |
+ pkg, *flags = line.split() |
31 |
try: |
32 |
# TODO: expand this invocation to allow threading token level validation down. |
33 |
# things like "is this a valid use flag?" |
34 |
- yield parse_match(v[0]), tuple(post_process(v[1:])), line, lineno, path |
35 |
+ yield parse_match(pkg), tuple(post_process(flags)), line, lineno, path |
36 |
except ParseError as e: |
37 |
logger.warning(f"{path!r}, line {lineno}: parsing error: {e}") |
38 |
|
39 |
@@ -90,30 +90,40 @@ def package_use_splitter(iterable): |
40 |
eapi_obj = get_latest_PMS_eapi() |
41 |
|
42 |
def f(tokens: list[str]): |
43 |
- |
44 |
+ start_idx = 0 |
45 |
i = iter(tokens) |
46 |
for idx, flag in enumerate(i): |
47 |
- if flag.endswith(":"): |
48 |
+ if flag == "-*": |
49 |
+ start_idx = idx |
50 |
+ elif flag.endswith(":"): |
51 |
# we encountered `USE_EXPAND:` , thus all following tokens |
52 |
# are values of that. |
53 |
- x = flag.lower()[:-1] |
54 |
- l = tokens[0:idx] |
55 |
+ use_expand = flag.lower()[:-1] |
56 |
+ yield from tokens[start_idx:idx] |
57 |
+ buffer: list[str] = [] |
58 |
for flag in i: |
59 |
if flag.endswith(":"): |
60 |
- x = flag.lower()[:-1] |
61 |
+ use_expand = flag.lower()[:-1] |
62 |
+ yield from buffer |
63 |
+ buffer.clear() |
64 |
+ continue |
65 |
+ if flag == "-*": |
66 |
+ buffer.clear() |
67 |
+ yield f"-{use_expand}_*" |
68 |
continue |
69 |
if flag.startswith("-"): |
70 |
- flag = f"-{x}_{flag[1:]}" |
71 |
+ flag = f"-{use_expand}_{flag[1:]}" |
72 |
else: |
73 |
- flag = f"{x}_{flag}" |
74 |
+ flag = f"{use_expand}_{flag}" |
75 |
if not eapi_obj.is_valid_use_flag(flag.lstrip("-")): |
76 |
raise ParseError(f"token {flag} is not a valid use flag") |
77 |
- l.append(flag) |
78 |
- return l |
79 |
+ buffer.append(flag) |
80 |
+ yield from buffer |
81 |
+ return |
82 |
elif not eapi_obj.is_valid_use_flag(flag.lstrip("-")): |
83 |
raise ParseError(f"token {flag} is not a valid use flag") |
84 |
# if we made it here, there's no USE_EXPAND; thus just return the original sequence |
85 |
- return tokens |
86 |
+ yield from tokens[start_idx:] |
87 |
|
88 |
return restriction_payload_splitter(iterable, post_process=f) |
89 |
|
90 |
@@ -600,10 +610,8 @@ class domain(config_domain): |
91 |
|
92 |
@klass.jit_attr_none |
93 |
def use_expand_re(self): |
94 |
- return re.compile( |
95 |
- "^(?:[+-])?(%s)_(.*)$" |
96 |
- % "|".join(x.lower() for x in self.profile.use_expand) |
97 |
- ) |
98 |
+ expands = "|".join(x.lower() for x in self.profile.use_expand) |
99 |
+ return re.compile(rf"^(?:[+-])?({expands})_(.*)$") |
100 |
|
101 |
def _split_use_expand_flags(self, use_stream): |
102 |
stream = ((self.use_expand_re.match(x), x) for x in use_stream) |
103 |
|
104 |
diff --git a/src/pkgcore/ebuild/misc.py b/src/pkgcore/ebuild/misc.py |
105 |
index 8c22b277f..eafcf6f60 100644 |
106 |
--- a/src/pkgcore/ebuild/misc.py |
107 |
+++ b/src/pkgcore/ebuild/misc.py |
108 |
@@ -66,8 +66,14 @@ def optimize_incrementals(sequence): |
109 |
finalized.add(item) |
110 |
|
111 |
|
112 |
-def incremental_chunked(orig, iterables): |
113 |
+def incremental_chunked(orig: set[str], iterables): |
114 |
for cinst in iterables: |
115 |
+ if "*" in cinst.neg: # remove all previous set flags |
116 |
+ orig.clear() |
117 |
+ for flag in cinst.neg: |
118 |
+ if flag.endswith("_*"): # remove previous USE_EXPAND |
119 |
+ drop = [f for f in orig if f.startswith(flag[:-2])] |
120 |
+ orig.difference_update(drop) |
121 |
orig.difference_update(cinst.neg) |
122 |
orig.update(cinst.pos) |
123 |
|
124 |
|
125 |
diff --git a/tests/ebuild/test_domain.py b/tests/ebuild/test_domain.py |
126 |
index e7b93b11b..54aa8f36b 100644 |
127 |
--- a/tests/ebuild/test_domain.py |
128 |
+++ b/tests/ebuild/test_domain.py |
129 |
@@ -57,15 +57,17 @@ class TestDomain: |
130 |
|
131 |
def test_use_expand_syntax(self): |
132 |
(self.pusedir / "a").write_text( |
133 |
- textwrap.dedent( |
134 |
- """ |
135 |
- */* x_y1 |
136 |
- # unrelated is there to verify that it's unaffected by the USE_EXPAND |
137 |
- */* unrelated X: -y1 y2 |
138 |
- # multiple USE_EXPANDs |
139 |
- */* unrelated X: -y1 y2 Z: -z3 z4 |
140 |
- """ |
141 |
- ) |
142 |
+ """ |
143 |
+ */* x_y1 |
144 |
+ # unrelated is there to verify that it's unaffected by the USE_EXPAND |
145 |
+ */* unrelated X: -y1 y2 |
146 |
+ # multiple USE_EXPANDs |
147 |
+ */* unrelated X: -y1 y2 Z: -z3 z4 |
148 |
+ # cleanup previous |
149 |
+ */* x y -* z |
150 |
+ # cleanup previous USE_EXPAND |
151 |
+ */* unrelated Y: y1 -* y2 Z: z1 -* -z2 |
152 |
+ """ |
153 |
) |
154 |
|
155 |
assert ( |
156 |
@@ -91,6 +93,27 @@ class TestDomain: |
157 |
), |
158 |
), |
159 |
), |
160 |
+ ( |
161 |
+ packages.AlwaysTrue, |
162 |
+ ( |
163 |
+ ("*",), |
164 |
+ ("z",), |
165 |
+ ), |
166 |
+ ), |
167 |
+ ( |
168 |
+ packages.AlwaysTrue, |
169 |
+ ( |
170 |
+ ( |
171 |
+ "y_*", |
172 |
+ "z_*", |
173 |
+ "z_z2", |
174 |
+ ), |
175 |
+ ( |
176 |
+ "unrelated", |
177 |
+ "y_y2", |
178 |
+ ), |
179 |
+ ), |
180 |
+ ), |
181 |
) == self.mk_domain().pkg_use |
182 |
|
183 |
def test_use_flag_parsing_enforcement(self, caplog): |