commit:     7c9f1da09e6660ba6f5eb4c677412c5c7c601c34
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Fri Jan 20 08:59:38 2023 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Fri Jan 20 08:59:38 2023 +0000
URL:        
https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=7c9f1da0

domain: support `-*` in use as previous removal

Add support for `-*` and `USE_EXPAND: -*` syntax. Allow this syntax, and
update incremental computation of resulting use combination.

Resolves: https://github.com/pkgcore/pkgcore/issues/393
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 src/pkgcore/ebuild/domain.py | 40 ++++++++++++++++++++++++----------------
 src/pkgcore/ebuild/misc.py   |  8 +++++++-
 tests/ebuild/test_domain.py  | 41 ++++++++++++++++++++++++++++++++---------
 3 files changed, 63 insertions(+), 26 deletions(-)

diff --git a/src/pkgcore/ebuild/domain.py b/src/pkgcore/ebuild/domain.py
index 0dba49d5d..fd5b39fc3 100644
--- a/src/pkgcore/ebuild/domain.py
+++ b/src/pkgcore/ebuild/domain.py
@@ -69,11 +69,11 @@ def package_masks(iterable):
 
 def restriction_payload_splitter(iterable, post_process=lambda x: x):
     for line, lineno, path in iterable:
-        v = line.split()
+        pkg, *flags = line.split()
         try:
             # TODO: expand this invocation to allow threading token level 
validation down.
             # things like "is this a valid use flag?"
-            yield parse_match(v[0]), tuple(post_process(v[1:])), line, lineno, 
path
+            yield parse_match(pkg), tuple(post_process(flags)), line, lineno, 
path
         except ParseError as e:
             logger.warning(f"{path!r}, line {lineno}: parsing error: {e}")
 
@@ -90,30 +90,40 @@ def package_use_splitter(iterable):
     eapi_obj = get_latest_PMS_eapi()
 
     def f(tokens: list[str]):
-
+        start_idx = 0
         i = iter(tokens)
         for idx, flag in enumerate(i):
-            if flag.endswith(":"):
+            if flag == "-*":
+                start_idx = idx
+            elif flag.endswith(":"):
                 # we encountered `USE_EXPAND:` , thus all following tokens
                 # are values of that.
-                x = flag.lower()[:-1]
-                l = tokens[0:idx]
+                use_expand = flag.lower()[:-1]
+                yield from tokens[start_idx:idx]
+                buffer: list[str] = []
                 for flag in i:
                     if flag.endswith(":"):
-                        x = flag.lower()[:-1]
+                        use_expand = flag.lower()[:-1]
+                        yield from buffer
+                        buffer.clear()
+                        continue
+                    if flag == "-*":
+                        buffer.clear()
+                        yield f"-{use_expand}_*"
                         continue
                     if flag.startswith("-"):
-                        flag = f"-{x}_{flag[1:]}"
+                        flag = f"-{use_expand}_{flag[1:]}"
                     else:
-                        flag = f"{x}_{flag}"
+                        flag = f"{use_expand}_{flag}"
                     if not eapi_obj.is_valid_use_flag(flag.lstrip("-")):
                         raise ParseError(f"token {flag} is not a valid use 
flag")
-                    l.append(flag)
-                return l
+                    buffer.append(flag)
+                yield from buffer
+                return
             elif not eapi_obj.is_valid_use_flag(flag.lstrip("-")):
                 raise ParseError(f"token {flag} is not a valid use flag")
         # if we made it here, there's no USE_EXPAND; thus just return the 
original sequence
-        return tokens
+        yield from tokens[start_idx:]
 
     return restriction_payload_splitter(iterable, post_process=f)
 
@@ -600,10 +610,8 @@ class domain(config_domain):
 
     @klass.jit_attr_none
     def use_expand_re(self):
-        return re.compile(
-            "^(?:[+-])?(%s)_(.*)$"
-            % "|".join(x.lower() for x in self.profile.use_expand)
-        )
+        expands = "|".join(x.lower() for x in self.profile.use_expand)
+        return re.compile(rf"^(?:[+-])?({expands})_(.*)$")
 
     def _split_use_expand_flags(self, use_stream):
         stream = ((self.use_expand_re.match(x), x) for x in use_stream)

diff --git a/src/pkgcore/ebuild/misc.py b/src/pkgcore/ebuild/misc.py
index 8c22b277f..eafcf6f60 100644
--- a/src/pkgcore/ebuild/misc.py
+++ b/src/pkgcore/ebuild/misc.py
@@ -66,8 +66,14 @@ def optimize_incrementals(sequence):
                 finalized.add(item)
 
 
-def incremental_chunked(orig, iterables):
+def incremental_chunked(orig: set[str], iterables):
     for cinst in iterables:
+        if "*" in cinst.neg:  # remove all previous set flags
+            orig.clear()
+        for flag in cinst.neg:
+            if flag.endswith("_*"):  # remove previous USE_EXPAND
+                drop = [f for f in orig if f.startswith(flag[:-2])]
+                orig.difference_update(drop)
         orig.difference_update(cinst.neg)
         orig.update(cinst.pos)
 

diff --git a/tests/ebuild/test_domain.py b/tests/ebuild/test_domain.py
index e7b93b11b..54aa8f36b 100644
--- a/tests/ebuild/test_domain.py
+++ b/tests/ebuild/test_domain.py
@@ -57,15 +57,17 @@ class TestDomain:
 
     def test_use_expand_syntax(self):
         (self.pusedir / "a").write_text(
-            textwrap.dedent(
-                """
-                */* x_y1
-                # unrelated is there to verify that it's unaffected by the 
USE_EXPAND
-                */* unrelated X: -y1 y2
-                # multiple USE_EXPANDs
-                */* unrelated X: -y1 y2 Z: -z3 z4
-                """
-            )
+            """
+            */* x_y1
+            # unrelated is there to verify that it's unaffected by the 
USE_EXPAND
+            */* unrelated X: -y1 y2
+            # multiple USE_EXPANDs
+            */* unrelated X: -y1 y2 Z: -z3 z4
+            # cleanup previous
+            */* x y -* z
+            # cleanup previous USE_EXPAND
+            */* unrelated Y: y1 -* y2 Z: z1 -* -z2
+            """
         )
 
         assert (
@@ -91,6 +93,27 @@ class TestDomain:
                     ),
                 ),
             ),
+            (
+                packages.AlwaysTrue,
+                (
+                    ("*",),
+                    ("z",),
+                ),
+            ),
+            (
+                packages.AlwaysTrue,
+                (
+                    (
+                        "y_*",
+                        "z_*",
+                        "z_z2",
+                    ),
+                    (
+                        "unrelated",
+                        "y_y2",
+                    ),
+                ),
+            ),
         ) == self.mk_domain().pkg_use
 
     def test_use_flag_parsing_enforcement(self, caplog):

Reply via email to