public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Arthur Zamarin" <arthurzam@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/pkgcore/pkgcore:master commit in: src/pkgcore/ebuild/, tests/ebuild/
Date: Sat,  8 Oct 2022 10:09:13 +0000 (UTC)	[thread overview]
Message-ID: <1665223099.3fa274977405f73221055c7287880a9dc3038765.arthurzam@gentoo> (raw)

commit:     3fa274977405f73221055c7287880a9dc3038765
Author:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
AuthorDate: Fri Oct  7 18:52:15 2022 +0000
Commit:     Arthur Zamarin <arthurzam <AT> gentoo <DOT> org>
CommitDate: Sat Oct  8 09:58:19 2022 +0000
URL:        https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=3fa27497

profiles: support package.bashrc files

Add support for `profile-bashrcs` profile format, which adds support for
per-profile bashrc mechanism `package.bashrc`, which enables to specify
per restriction the extra bashrc files to run.

See portage(5) for format details.

Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org>

 src/pkgcore/ebuild/domain.py          |  9 +++---
 src/pkgcore/ebuild/inspect_profile.py |  9 ++++++
 src/pkgcore/ebuild/profiles.py        | 26 ++++++++++++++++
 src/pkgcore/ebuild/repo_objs.py       |  2 +-
 tests/ebuild/test_profiles.py         | 56 +++++++++++++++++++++++++++++++++++
 5 files changed, 97 insertions(+), 5 deletions(-)

diff --git a/src/pkgcore/ebuild/domain.py b/src/pkgcore/ebuild/domain.py
index 47f31ef2f..a1f231e9f 100644
--- a/src/pkgcore/ebuild/domain.py
+++ b/src/pkgcore/ebuild/domain.py
@@ -596,10 +596,11 @@ class domain(config_domain):
         return self
 
     def get_package_bashrcs(self, pkg):
-        for source in self.profile.bashrcs:
-            yield source
-        for source in self.bashrcs:
-            yield source
+        yield from self.profile.bashrcs
+        for restrict, bashrcs in self.profile.pkg_bashrcs:
+            if restrict.match(pkg):
+                yield from bashrcs
+        yield from self.bashrcs
         if not os.path.exists(self.ebuild_hook_dir):
             return
         # matching portage behavior... it's whacked.

diff --git a/src/pkgcore/ebuild/inspect_profile.py b/src/pkgcore/ebuild/inspect_profile.py
index a0be246c1..dc8c5942d 100644
--- a/src/pkgcore/ebuild/inspect_profile.py
+++ b/src/pkgcore/ebuild/inspect_profile.py
@@ -187,6 +187,15 @@ class bashrcs(_base, metaclass=_register_command):
             out.write(bashrc.path)
 
 
+class package_bashrc(_base, metaclass=_register_command):
+    """inspect package.bashrc"""
+
+    def __call__(self, namespace, out, err):
+        for package, bashrcs in namespace.profile.pkg_bashrcs:
+            bashrcs = ", ".join(s.path for s in bashrcs)
+            out.write(f'{package}: {bashrcs}')
+
+
 class keywords(_base, metaclass=_register_command):
     """inspect package.keywords"""
 

diff --git a/src/pkgcore/ebuild/profiles.py b/src/pkgcore/ebuild/profiles.py
index 4607639cb..34e839e9b 100644
--- a/src/pkgcore/ebuild/profiles.py
+++ b/src/pkgcore/ebuild/profiles.py
@@ -452,6 +452,27 @@ class ProfileNode(metaclass=caching.WeakInstMeta):
             return local_source(path)
         return None
 
+    @load_property("package.bashrc", allow_recurse=True)
+    def pkg_bashrc(self, data):
+        repo_config = self.repoconfig
+        if repo_config is None or 'profile-bashrcs' not in repo_config.profile_formats:
+            return ()
+
+        d = defaultdict(list)
+        for line, lineno, relpath in data:
+            l = line.split()
+            try:
+                a = self.eapi_atom(l[0])
+            except ebuild_errors.MalformedAtom as exc:
+                logger.error(f'{relpath!r}, line {lineno}: parsing error: {exc}')
+                continue
+            if len(l) == 1:
+                logger.error(f'{relpath!r}, line {lineno}: missing bashrc files: {line!r}')
+                continue
+            for filename in l[1:]:
+                d[a].append(local_source(pjoin(self.path, 'bashrc', filename)))
+        return tuple((k, tuple(v)) for k, v in d.items())
+
     @load_property('eapi', fallback='0')
     def eapi(self, data):
         # handle fallback
@@ -522,6 +543,7 @@ class EmptyRootNode(ProfileNode):
     deprecated = None
     pkg_use = masked_use = stable_masked_use = forced_use = stable_forced_use = misc.ChunkedDataDict()
     forced_use.freeze()
+    pkg_bashrc = ()
     pkg_use_force = pkg_use_mask = ImmutableDict()
     pkg_provided = system = profile_set = ((), ())
 
@@ -747,6 +769,10 @@ class ProfileStack:
     def bashrcs(self):
         return tuple(x.bashrc for x in self.stack if x.bashrc is not None)
 
+    @klass.jit_attr
+    def pkg_bashrcs(self):
+        return tuple(chain.from_iterable(x.pkg_bashrc for x in self.stack))
+
     bashrc = klass.alias_attr("bashrcs")
     path = klass.alias_attr("node.path")
 

diff --git a/src/pkgcore/ebuild/repo_objs.py b/src/pkgcore/ebuild/repo_objs.py
index 633c858e3..78371e29a 100644
--- a/src/pkgcore/ebuild/repo_objs.py
+++ b/src/pkgcore/ebuild/repo_objs.py
@@ -682,7 +682,7 @@ class RepoConfig(syncable.tree, klass.ImmutableInstance, metaclass=WeakInstMeta)
 
     default_hashes = ('size', 'blake2b', 'sha512')
     default_required_hashes = ('size', 'blake2b')
-    supported_profile_formats = ('pms', 'portage-1', 'portage-2', 'profile-set')
+    supported_profile_formats = ('pms', 'portage-1', 'portage-2', 'profile-bashrcs', 'profile-set')
     supported_cache_formats = ('md5-dict', 'pms')
 
     __inst_caching__ = True

diff --git a/tests/ebuild/test_profiles.py b/tests/ebuild/test_profiles.py
index 8f920825c..a7abfe9f2 100644
--- a/tests/ebuild/test_profiles.py
+++ b/tests/ebuild/test_profiles.py
@@ -545,6 +545,17 @@ class TestPmsProfileNode(profile_mixin):
         self.write_file(tmp_path, "profile.bashrc", '')
         assert self.klass(path).bashrc is not None
 
+    def test_pkg_bashrc(self, tmp_path, caplog):
+        path = tmp_path / self.profile
+        assert not self.klass(path).pkg_bashrc
+        self.write_file(tmp_path, "package.bashrc", "@dsfg", profile=self.profile)
+        assert not self.klass(path).pkg_bashrc
+        self.write_file(tmp_path, "package.bashrc", "dev-util/foo", profile=self.profile)
+        assert not self.klass(path).pkg_bashrc
+        self.write_file(tmp_path, "package.bashrc", "dev-util/foo file1 file2\ndev-util/bar file3", profile=self.profile)
+        assert not self.klass(path).pkg_bashrc
+        assert not caplog.text
+
 
 class TestPortage1ProfileNode(TestPmsProfileNode):
 
@@ -593,6 +604,51 @@ class TestPortage2ProfileNode(TestPortage1ProfileNode):
         (tmp_path / "metadata" / "layout.conf").write_text("masters = ''\nprofile-formats = portage-2")
 
 
+class TestProfileBashrcProfileNode(TestPmsProfileNode):
+
+    profile = os.path.join("profiles", "default")
+
+    def assert_pkg_bashrc(self, actual, expected):
+        assert expected == {
+            str(k): [s.path for s in v]
+            for k, v in actual
+        }
+
+    def setup_repo(self, tmp_path):
+        (tmp_path / "profiles" / "repo_name").write_bytes(binascii.b2a_hex(os.urandom(10)))
+        (tmp_path / "metadata").mkdir()
+        (tmp_path / "metadata" / "layout.conf").write_text("masters = ''\nprofile-formats = profile-bashrcs")
+
+    def test_pkg_bashrc(self, tmp_path, caplog):
+        path = tmp_path / self.profile
+        assert not self.klass(path).pkg_bashrc
+        self.parsing_checks(tmp_path, "package.bashrc", "pkg_bashrc")
+        assert not caplog.text
+
+        caplog.clear()
+        self.write_file(tmp_path, "package.bashrc", "@dsfg", profile=self.profile)
+        assert not self.klass(path).pkg_bashrc
+        assert "line 1: parsing error: invalid package atom: '@dsfg'" in caplog.text
+
+        caplog.clear()
+        self.write_file(tmp_path, "package.bashrc", "dev-util/foo", profile=self.profile)
+        assert not self.klass(path).pkg_bashrc
+        assert "line 1: missing bashrc files: 'dev-util/foo'" in caplog.text
+
+        caplog.clear()
+        self.write_file(tmp_path, "package.bashrc", "dev-util/foo file1", profile=self.profile)
+        self.assert_pkg_bashrc(self.klass(path).pkg_bashrc, {"dev-util/foo": [str(path / "bashrc/file1")]})
+        assert not caplog.text
+
+        caplog.clear()
+        self.write_file(tmp_path, "package.bashrc", "dev-util/foo file1 file2\ndev-util/bar file3", profile=self.profile)
+        self.assert_pkg_bashrc(self.klass(path).pkg_bashrc, {
+            "dev-util/foo": [str(path / "bashrc/file1"), str(path / "bashrc/file2")],
+            "dev-util/bar": [str(path / "bashrc/file3")],
+        })
+        assert not caplog.text
+
+
 class TestProfileSetProfileNode(TestPmsProfileNode):
 
     profile = os.path.join("profiles", "default")


             reply	other threads:[~2022-10-08 10:09 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-08 10:09 Arthur Zamarin [this message]
  -- strict thread matches above, loose matches on Subject: below --
2022-12-22  7:11 [gentoo-commits] proj/pkgcore/pkgcore:master commit in: src/pkgcore/ebuild/, tests/ebuild/ Arthur Zamarin
2023-08-28 17:49 Arthur Zamarin
2023-12-26 17:45 Arthur Zamarin
2024-01-12  7:13 Arthur Zamarin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1665223099.3fa274977405f73221055c7287880a9dc3038765.arthurzam@gentoo \
    --to=arthurzam@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox