* [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles
@ 2025-12-17 7:10 Louis Chauvet
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths Louis Chauvet
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Louis Chauvet @ 2025-12-17 7:10 UTC (permalink / raw
To: gentoo-portage-dev; +Cc: thomas.petazzoni, Louis Chauvet, Sam James
Currently profiles does not allow using per-package license unmasking.
The only solution is the LICENSE variable, which apply to all the packages.
To allow this, add support for package.license in profile.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
Louis Chauvet (4):
lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths
lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license
tests/test_config: Refactor LicenseManager testing to test multiple configurations
tests/test_config: Add test for package.license in profiles
.../package/ebuild/_config/LicenseManager.py | 9 +-
lib/portage/package/ebuild/config.py | 3 +-
lib/portage/tests/ebuild/test_config.py | 215 ++++++++++++---------
man/portage.5 | 1 +
4 files changed, 130 insertions(+), 98 deletions(-)
---
base-commit: d7d6fd54f1c936e89c5e4467c6c1f33b217325ca
change-id: 20251216-add_package_license_to_profiles-c6f695182aa3
Best regards,
--
Louis Chauvet <louis.chauvet@bootlin.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths
2025-12-17 7:10 [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Louis Chauvet
@ 2025-12-17 7:10 ` Louis Chauvet
2025-12-18 1:26 ` Sam James
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 2/4] lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license Louis Chauvet
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Louis Chauvet @ 2025-12-17 7:10 UTC (permalink / raw
To: gentoo-portage-dev; +Cc: thomas.petazzoni, Louis Chauvet
Currently LicenseManager only get the list of all profile locations. This
is enough for reading all license groups, but not for parsing
profile-specific package.license.
Directly pass the LocationsManager so LicenseManager can read
LicenseManager.profiles and read package.license.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
lib/portage/package/ebuild/_config/LicenseManager.py | 7 ++++---
lib/portage/package/ebuild/config.py | 3 +--
lib/portage/tests/ebuild/test_config.py | 9 +++------
3 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/lib/portage/package/ebuild/_config/LicenseManager.py b/lib/portage/package/ebuild/_config/LicenseManager.py
index 90f7742e301c..c59fff6ea4f2 100644
--- a/lib/portage/package/ebuild/_config/LicenseManager.py
+++ b/lib/portage/package/ebuild/_config/LicenseManager.py
@@ -14,20 +14,21 @@ from portage.package.ebuild._config.helper import ordered_by_atom_specificity
class LicenseManager:
- def __init__(self, license_group_locations, abs_user_config, user_config=True):
+ def __init__(self, locations_manager, user_config=True):
self._accept_license_str = None
self._accept_license = None
self._license_groups = {}
self._plicensedict = ExtendedAtomDict(dict)
self._undef_lic_groups = set()
+ license_group_locations = list(locations_manager.profile_locations)
if user_config:
- license_group_locations = list(license_group_locations) + [abs_user_config]
+ license_group_locations.append(locations_manager.abs_user_config)
self._read_license_groups(license_group_locations)
if user_config:
- self._read_user_config(abs_user_config)
+ self._read_user_config(locations_manager.abs_user_config)
def _read_user_config(self, abs_user_config):
licdict = grabdict_package(
diff --git a/lib/portage/package/ebuild/config.py b/lib/portage/package/ebuild/config.py
index 4f60a71e7011..718f367eb2ed 100644
--- a/lib/portage/package/ebuild/config.py
+++ b/lib/portage/package/ebuild/config.py
@@ -847,8 +847,7 @@ class config:
# Read license_groups and optionally license_groups and package.license from user config
self._license_manager = LicenseManager(
- locations_manager.profile_locations,
- abs_user_config,
+ locations_manager,
user_config=local_config,
)
# Extract '*/*' entries from package.license
diff --git a/lib/portage/tests/ebuild/test_config.py b/lib/portage/tests/ebuild/test_config.py
index 743b30bfb0d6..83046a7dc97b 100644
--- a/lib/portage/tests/ebuild/test_config.py
+++ b/lib/portage/tests/ebuild/test_config.py
@@ -7,6 +7,7 @@ import portage
from portage import os, shutil, _encodings
from portage.const import USER_CONFIG_PATH
from portage.dep import Atom
+from portage.package.ebuild._config.LocationsManager import LocationsManager
from portage.package.ebuild.config import config
from portage.package.ebuild._config.LicenseManager import LicenseManager
from portage.tests import TestCase
@@ -95,17 +96,13 @@ class ConfigTestCase(TestCase):
}
playground = ResolverPlayground(user_config=user_config)
+ settings = config(clone=playground.settings)
try:
portage.util.noiselimit = -2
- license_group_locations = (
- os.path.join(
- playground.settings.repositories["test_repo"].location, "profiles"
- ),
- )
pkg_license = os.path.join(playground.eroot, "etc", "portage")
- lic_man = LicenseManager(license_group_locations, pkg_license)
+ lic_man = LicenseManager(settings._locations_manager, pkg_license)
self.assertEqual(lic_man._accept_license_str, None)
self.assertEqual(lic_man._accept_license, None)
--
2.51.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [gentoo-portage-dev] [PATCH RESEND 2/4] lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license
2025-12-17 7:10 [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Louis Chauvet
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths Louis Chauvet
@ 2025-12-17 7:10 ` Louis Chauvet
2025-12-18 1:27 ` [gentoo-portage-dev] " Sam James
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 3/4] tests/test_config: Refactor LicenseManager testing to test multiple configurations Louis Chauvet
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: Louis Chauvet @ 2025-12-17 7:10 UTC (permalink / raw
To: gentoo-portage-dev; +Cc: thomas.petazzoni, Louis Chauvet, Sam James
Currently the only way to unmask license in profile is to use the LICENSE
variable in make.defaults. This may be acceptable for "unique" licenses
(linux-fw-redistributable, only used by one package), but not practical for
"generic" licenses.
Read profile-specific package.license in LicenseManager so per-profile
per-pacakge license can be configured.
Suggested-by: Sam James <sam@gentoo.org>
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
lib/portage/package/ebuild/_config/LicenseManager.py | 2 ++
man/portage.5 | 1 +
2 files changed, 3 insertions(+)
diff --git a/lib/portage/package/ebuild/_config/LicenseManager.py b/lib/portage/package/ebuild/_config/LicenseManager.py
index c59fff6ea4f2..f515740071a7 100644
--- a/lib/portage/package/ebuild/_config/LicenseManager.py
+++ b/lib/portage/package/ebuild/_config/LicenseManager.py
@@ -28,6 +28,8 @@ class LicenseManager:
self._read_license_groups(license_group_locations)
if user_config:
+ for profile in locations_manager.profiles:
+ self._read_user_config(profile)
self._read_user_config(locations_manager.abs_user_config)
def _read_user_config(self, abs_user_config):
diff --git a/man/portage.5 b/man/portage.5
index d7b2063e0fc2..787fc18e1a9f 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -26,6 +26,7 @@ packages.build
package.accept_keywords
package.bashrc
package.keywords
+package.license
package.mask
package.provided
package.unmask
--
2.51.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [gentoo-portage-dev] [PATCH RESEND 3/4] tests/test_config: Refactor LicenseManager testing to test multiple configurations
2025-12-17 7:10 [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Louis Chauvet
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths Louis Chauvet
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 2/4] lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license Louis Chauvet
@ 2025-12-17 7:10 ` Louis Chauvet
2025-12-18 1:27 ` Sam James
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 4/4] tests/test_config: Add test for package.license in profiles Louis Chauvet
2025-12-17 9:33 ` [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Ulrich Müller
4 siblings, 1 reply; 13+ messages in thread
From: Louis Chauvet @ 2025-12-17 7:10 UTC (permalink / raw
To: gentoo-portage-dev; +Cc: thomas.petazzoni, Louis Chauvet
In order to easly test per-profile per-package license unmasking, extract
common code from testLicenseManager.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
lib/portage/tests/ebuild/test_config.py | 181 ++++++++++++++++----------------
1 file changed, 88 insertions(+), 93 deletions(-)
diff --git a/lib/portage/tests/ebuild/test_config.py b/lib/portage/tests/ebuild/test_config.py
index 83046a7dc97b..b36073504b11 100644
--- a/lib/portage/tests/ebuild/test_config.py
+++ b/lib/portage/tests/ebuild/test_config.py
@@ -83,16 +83,94 @@ class ConfigTestCase(TestCase):
finally:
playground.cleanup()
+ _testLicenseManagerPackageLicense = (
+ "dev-libs/* TEST",
+ "dev-libs/A -TEST2",
+ "=dev-libs/A-2 TEST3 @TEST",
+ "*/* @EULA TEST2",
+ "=dev-libs/C-1 *",
+ "=dev-libs/C-2 -*",
+ )
+
+ def _testLicenseManager(self, lic_man):
+ self.assertEqual(lic_man._accept_license_str, None)
+ self.assertEqual(lic_man._accept_license, None)
+ self.assertEqual(lic_man._license_groups, {"EULA": frozenset(["TEST"])})
+ self.assertEqual(lic_man._undef_lic_groups, {"TEST"})
+
+ self.assertEqual(lic_man.extract_global_changes(), "TEST TEST2")
+ self.assertEqual(lic_man.extract_global_changes(), "")
+
+ lic_man.set_accept_license_str("TEST TEST2")
+ self.assertEqual(
+ lic_man._getPkgAcceptLicense("dev-libs/B-1", "0", None),
+ ["TEST", "TEST2", "TEST"],
+ )
+ self.assertEqual(
+ lic_man._getPkgAcceptLicense("dev-libs/A-1", "0", None),
+ ["TEST", "TEST2", "TEST", "-TEST2"],
+ )
+ self.assertEqual(
+ lic_man._getPkgAcceptLicense("dev-libs/A-2", "0", None),
+ ["TEST", "TEST2", "TEST", "-TEST2", "TEST3", "@TEST"],
+ )
+
+ self.assertEqual(
+ lic_man.get_prunned_accept_license("dev-libs/B-1", [], "TEST", "0", None),
+ "TEST",
+ )
+ self.assertEqual(
+ lic_man.get_prunned_accept_license("dev-libs/A-1", [], "-TEST2", "0", None),
+ "",
+ )
+ self.assertEqual(
+ lic_man.get_prunned_accept_license(
+ "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
+ ),
+ "TEST",
+ )
+ self.assertEqual(
+ lic_man.get_prunned_accept_license("dev-libs/C-1", [], "TEST5", "0", None),
+ "TEST5",
+ )
+ self.assertEqual(
+ lic_man.get_prunned_accept_license("dev-libs/C-2", [], "TEST2", "0", None),
+ "",
+ )
+
+ self.assertEqual(
+ lic_man.getMissingLicenses("dev-libs/B-1", [], "TEST", "0", None), []
+ )
+ self.assertEqual(
+ lic_man.getMissingLicenses("dev-libs/A-1", [], "-TEST2", "0", None),
+ ["-TEST2"],
+ )
+ self.assertEqual(
+ lic_man.getMissingLicenses(
+ "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
+ ),
+ [],
+ )
+ self.assertEqual(
+ lic_man.getMissingLicenses(
+ "dev-libs/A-3", [], "|| ( TEST2 || ( TEST3 TEST4 ) )", "0", None
+ ),
+ ["TEST2", "TEST3", "TEST4"],
+ )
+ self.assertEqual(
+ lic_man.getMissingLicenses("dev-libs/C-1", [], "TEST5", "0", None), []
+ )
+ self.assertEqual(
+ lic_man.getMissingLicenses("dev-libs/C-2", [], "TEST2", "0", None),
+ ["TEST2"],
+ )
+ self.assertEqual(
+ lic_man.getMissingLicenses("dev-libs/D-1", [], "", "0", None), []
+ )
+
def testLicenseManager(self):
user_config = {
- "package.license": (
- "dev-libs/* TEST",
- "dev-libs/A -TEST2",
- "=dev-libs/A-2 TEST3 @TEST",
- "*/* @EULA TEST2",
- "=dev-libs/C-1 *",
- "=dev-libs/C-2 -*",
- ),
+ "package.license": self._testLicenseManagerPackageLicense,
}
playground = ResolverPlayground(user_config=user_config)
@@ -100,92 +178,9 @@ class ConfigTestCase(TestCase):
try:
portage.util.noiselimit = -2
- pkg_license = os.path.join(playground.eroot, "etc", "portage")
-
- lic_man = LicenseManager(settings._locations_manager, pkg_license)
-
- self.assertEqual(lic_man._accept_license_str, None)
- self.assertEqual(lic_man._accept_license, None)
- self.assertEqual(lic_man._license_groups, {"EULA": frozenset(["TEST"])})
- self.assertEqual(lic_man._undef_lic_groups, {"TEST"})
-
- self.assertEqual(lic_man.extract_global_changes(), "TEST TEST2")
- self.assertEqual(lic_man.extract_global_changes(), "")
-
- lic_man.set_accept_license_str("TEST TEST2")
- self.assertEqual(
- lic_man._getPkgAcceptLicense("dev-libs/B-1", "0", None),
- ["TEST", "TEST2", "TEST"],
- )
- self.assertEqual(
- lic_man._getPkgAcceptLicense("dev-libs/A-1", "0", None),
- ["TEST", "TEST2", "TEST", "-TEST2"],
- )
- self.assertEqual(
- lic_man._getPkgAcceptLicense("dev-libs/A-2", "0", None),
- ["TEST", "TEST2", "TEST", "-TEST2", "TEST3", "@TEST"],
- )
-
- self.assertEqual(
- lic_man.get_prunned_accept_license(
- "dev-libs/B-1", [], "TEST", "0", None
- ),
- "TEST",
- )
- self.assertEqual(
- lic_man.get_prunned_accept_license(
- "dev-libs/A-1", [], "-TEST2", "0", None
- ),
- "",
- )
- self.assertEqual(
- lic_man.get_prunned_accept_license(
- "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
- ),
- "TEST",
- )
- self.assertEqual(
- lic_man.get_prunned_accept_license(
- "dev-libs/C-1", [], "TEST5", "0", None
- ),
- "TEST5",
- )
- self.assertEqual(
- lic_man.get_prunned_accept_license(
- "dev-libs/C-2", [], "TEST2", "0", None
- ),
- "",
- )
+ lic_man = LicenseManager(settings._locations_manager)
+ self._testLicenseManager(lic_man)
- self.assertEqual(
- lic_man.getMissingLicenses("dev-libs/B-1", [], "TEST", "0", None), []
- )
- self.assertEqual(
- lic_man.getMissingLicenses("dev-libs/A-1", [], "-TEST2", "0", None),
- ["-TEST2"],
- )
- self.assertEqual(
- lic_man.getMissingLicenses(
- "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
- ),
- [],
- )
- self.assertEqual(
- lic_man.getMissingLicenses(
- "dev-libs/A-3", [], "|| ( TEST2 || ( TEST3 TEST4 ) )", "0", None
- ),
- ["TEST2", "TEST3", "TEST4"],
- )
- self.assertEqual(
- lic_man.getMissingLicenses("dev-libs/C-1", [], "TEST5", "0", None), []
- )
- self.assertEqual(
- lic_man.getMissingLicenses("dev-libs/C-2", [], "TEST2", "0", None),
- ["TEST2"],
- )
- self.assertEqual(
- lic_man.getMissingLicenses("dev-libs/D-1", [], "", "0", None), []
- )
finally:
portage.util.noiselimit = 0
playground.cleanup()
--
2.51.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [gentoo-portage-dev] [PATCH RESEND 4/4] tests/test_config: Add test for package.license in profiles
2025-12-17 7:10 [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Louis Chauvet
` (2 preceding siblings ...)
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 3/4] tests/test_config: Refactor LicenseManager testing to test multiple configurations Louis Chauvet
@ 2025-12-17 7:10 ` Louis Chauvet
2025-12-18 1:28 ` Sam James
2025-12-17 9:33 ` [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Ulrich Müller
4 siblings, 1 reply; 13+ messages in thread
From: Louis Chauvet @ 2025-12-17 7:10 UTC (permalink / raw
To: gentoo-portage-dev; +Cc: thomas.petazzoni, Louis Chauvet
Now package.license can be read from profiles, add two tests to ensure that
user and profile configuration are properly read.
Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
---
lib/portage/tests/ebuild/test_config.py | 37 +++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/lib/portage/tests/ebuild/test_config.py b/lib/portage/tests/ebuild/test_config.py
index b36073504b11..43940987254b 100644
--- a/lib/portage/tests/ebuild/test_config.py
+++ b/lib/portage/tests/ebuild/test_config.py
@@ -185,6 +185,43 @@ class ConfigTestCase(TestCase):
portage.util.noiselimit = 0
playground.cleanup()
+ def testLicenseManagerProfile(self):
+ profile_config = {
+ "package.license": self._testLicenseManagerPackageLicense,
+ }
+
+ playground = ResolverPlayground(profile=profile_config)
+ settings = config(clone=playground.settings)
+ try:
+ portage.util.noiselimit = -2
+
+ lic_man = LicenseManager(settings._locations_manager)
+ self._testLicenseManager(lic_man)
+
+ finally:
+ portage.util.noiselimit = 0
+ playground.cleanup()
+
+ def testLicenseManagerMixed(self):
+ profile_config = {
+ "package.license": self._testLicenseManagerPackageLicense[:4],
+ }
+ user_config = {
+ "package.license": self._testLicenseManagerPackageLicense[4:],
+ }
+
+ playground = ResolverPlayground(user_config=user_config, profile=profile_config)
+ settings = config(clone=playground.settings)
+ try:
+ portage.util.noiselimit = -2
+
+ lic_man = LicenseManager(settings._locations_manager)
+ self._testLicenseManager(lic_man)
+
+ finally:
+ portage.util.noiselimit = 0
+ playground.cleanup()
+
def testPackageMaskOrder(self):
ebuilds = {
"dev-libs/A-1": {},
--
2.51.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles
2025-12-17 7:10 [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Louis Chauvet
` (3 preceding siblings ...)
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 4/4] tests/test_config: Add test for package.license in profiles Louis Chauvet
@ 2025-12-17 9:33 ` Ulrich Müller
2025-12-17 10:15 ` Michael Orlitzky
2025-12-17 11:10 ` Louis Chauvet
4 siblings, 2 replies; 13+ messages in thread
From: Ulrich Müller @ 2025-12-17 9:33 UTC (permalink / raw
To: Louis Chauvet; +Cc: gentoo-portage-dev, thomas.petazzoni, Sam James
[-- Attachment #1: Type: text/plain, Size: 372 bytes --]
>>>>> On Wed, 17 Dec 2025, Louis Chauvet wrote:
> Currently profiles does not allow using per-package license unmasking.
> The only solution is the LICENSE variable, which apply to all the packages.
What would be the application for this? I understand package.license
in user configuration, but why would we ever want to unmask nonfree
per-package licenses in profiles?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 544 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles
2025-12-17 9:33 ` [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Ulrich Müller
@ 2025-12-17 10:15 ` Michael Orlitzky
2025-12-17 11:10 ` Louis Chauvet
1 sibling, 0 replies; 13+ messages in thread
From: Michael Orlitzky @ 2025-12-17 10:15 UTC (permalink / raw
To: gentoo-portage-dev; +Cc: Louis Chauvet, thomas.petazzoni, Sam James
On 2025-12-17 10:33:47, Ulrich Müller wrote:
>
> > Currently profiles does not allow using per-package license unmasking.
> > The only solution is the LICENSE variable, which apply to all the packages.
>
> What would be the application for this? I understand package.license
> in user configuration, but why would we ever want to unmask nonfree
> per-package licenses in profiles?
I would unmask e.g.
sys-firmware/intel-microcode intel-ucode
in the custom profile I use at work for all of our intel servers.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles
2025-12-17 9:33 ` [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Ulrich Müller
2025-12-17 10:15 ` Michael Orlitzky
@ 2025-12-17 11:10 ` Louis Chauvet
2025-12-18 1:28 ` Sam James
1 sibling, 1 reply; 13+ messages in thread
From: Louis Chauvet @ 2025-12-17 11:10 UTC (permalink / raw
To: Ulrich Müller; +Cc: gentoo-portage-dev, thomas.petazzoni, Sam James
On 12/17/25 10:33, Ulrich Müller wrote:
>>>>>> On Wed, 17 Dec 2025, Louis Chauvet wrote:
>
>> Currently profiles does not allow using per-package license unmasking.
>> The only solution is the LICENSE variable, which apply to all the packages.
>
> What would be the application for this? I understand package.license
> in user configuration, but why would we ever want to unmask nonfree
> per-package licenses in profiles?
My goal is to create my own custom profile to use the same set of
packages, version, use between my laptop and my desktop.
I have some non-free packages (linux-firmware, Saleae, intel-microcode),
so for me that make sense to have a package.license file in the profile.
For information, I also opened a pull request on Codeberg [1] because I
wasn’t sure if the mailing list was active.
[1]:https://codeberg.org/gentoo/portage/pulls/1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths Louis Chauvet
@ 2025-12-18 1:26 ` Sam James
0 siblings, 0 replies; 13+ messages in thread
From: Sam James @ 2025-12-18 1:26 UTC (permalink / raw
To: Louis Chauvet; +Cc: gentoo-portage-dev, thomas.petazzoni
Louis Chauvet <louis.chauvet@bootlin.com> writes:
> Currently LicenseManager only get the list of all profile locations. This
> is enough for reading all license groups, but not for parsing
> profile-specific package.license.
>
> Directly pass the LocationsManager so LicenseManager can read
> LicenseManager.profiles and read package.license.
>
Reviewed-by: Sam James <sam@gentoo.org>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
> lib/portage/package/ebuild/_config/LicenseManager.py | 7 ++++---
> lib/portage/package/ebuild/config.py | 3 +--
> lib/portage/tests/ebuild/test_config.py | 9 +++------
> 3 files changed, 8 insertions(+), 11 deletions(-)
>
> diff --git a/lib/portage/package/ebuild/_config/LicenseManager.py b/lib/portage/package/ebuild/_config/LicenseManager.py
> index 90f7742e301c..c59fff6ea4f2 100644
> --- a/lib/portage/package/ebuild/_config/LicenseManager.py
> +++ b/lib/portage/package/ebuild/_config/LicenseManager.py
> @@ -14,20 +14,21 @@ from portage.package.ebuild._config.helper import ordered_by_atom_specificity
>
>
> class LicenseManager:
> - def __init__(self, license_group_locations, abs_user_config, user_config=True):
> + def __init__(self, locations_manager, user_config=True):
> self._accept_license_str = None
> self._accept_license = None
> self._license_groups = {}
> self._plicensedict = ExtendedAtomDict(dict)
> self._undef_lic_groups = set()
>
> + license_group_locations = list(locations_manager.profile_locations)
> if user_config:
> - license_group_locations = list(license_group_locations) + [abs_user_config]
> + license_group_locations.append(locations_manager.abs_user_config)
>
> self._read_license_groups(license_group_locations)
>
> if user_config:
> - self._read_user_config(abs_user_config)
> + self._read_user_config(locations_manager.abs_user_config)
>
> def _read_user_config(self, abs_user_config):
> licdict = grabdict_package(
> diff --git a/lib/portage/package/ebuild/config.py b/lib/portage/package/ebuild/config.py
> index 4f60a71e7011..718f367eb2ed 100644
> --- a/lib/portage/package/ebuild/config.py
> +++ b/lib/portage/package/ebuild/config.py
> @@ -847,8 +847,7 @@ class config:
>
> # Read license_groups and optionally license_groups and package.license from user config
> self._license_manager = LicenseManager(
> - locations_manager.profile_locations,
> - abs_user_config,
> + locations_manager,
> user_config=local_config,
> )
> # Extract '*/*' entries from package.license
> diff --git a/lib/portage/tests/ebuild/test_config.py b/lib/portage/tests/ebuild/test_config.py
> index 743b30bfb0d6..83046a7dc97b 100644
> --- a/lib/portage/tests/ebuild/test_config.py
> +++ b/lib/portage/tests/ebuild/test_config.py
> @@ -7,6 +7,7 @@ import portage
> from portage import os, shutil, _encodings
> from portage.const import USER_CONFIG_PATH
> from portage.dep import Atom
> +from portage.package.ebuild._config.LocationsManager import LocationsManager
> from portage.package.ebuild.config import config
> from portage.package.ebuild._config.LicenseManager import LicenseManager
> from portage.tests import TestCase
> @@ -95,17 +96,13 @@ class ConfigTestCase(TestCase):
> }
>
> playground = ResolverPlayground(user_config=user_config)
> + settings = config(clone=playground.settings)
> try:
> portage.util.noiselimit = -2
>
> - license_group_locations = (
> - os.path.join(
> - playground.settings.repositories["test_repo"].location, "profiles"
> - ),
> - )
> pkg_license = os.path.join(playground.eroot, "etc", "portage")
>
> - lic_man = LicenseManager(license_group_locations, pkg_license)
> + lic_man = LicenseManager(settings._locations_manager, pkg_license)
>
> self.assertEqual(lic_man._accept_license_str, None)
> self.assertEqual(lic_man._accept_license, None)
^ permalink raw reply [flat|nested] 13+ messages in thread
* [gentoo-portage-dev] Re: [PATCH RESEND 2/4] lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 2/4] lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license Louis Chauvet
@ 2025-12-18 1:27 ` Sam James
0 siblings, 0 replies; 13+ messages in thread
From: Sam James @ 2025-12-18 1:27 UTC (permalink / raw
To: Louis Chauvet; +Cc: gentoo-portage-dev, thomas.petazzoni
Louis Chauvet <louis.chauvet@bootlin.com> writes:
> Currently the only way to unmask license in profile is to use the LICENSE
> variable in make.defaults. This may be acceptable for "unique" licenses
> (linux-fw-redistributable, only used by one package), but not practical for
> "generic" licenses.
>
> Read profile-specific package.license in LicenseManager so per-profile
> per-pacakge license can be configured.
>
Reviewed-by: Sam James <sam@gentoo.org>
> Suggested-by: Sam James <sam@gentoo.org>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
> lib/portage/package/ebuild/_config/LicenseManager.py | 2 ++
> man/portage.5 | 1 +
> 2 files changed, 3 insertions(+)
>
> diff --git a/lib/portage/package/ebuild/_config/LicenseManager.py b/lib/portage/package/ebuild/_config/LicenseManager.py
> index c59fff6ea4f2..f515740071a7 100644
> --- a/lib/portage/package/ebuild/_config/LicenseManager.py
> +++ b/lib/portage/package/ebuild/_config/LicenseManager.py
> @@ -28,6 +28,8 @@ class LicenseManager:
> self._read_license_groups(license_group_locations)
>
> if user_config:
> + for profile in locations_manager.profiles:
> + self._read_user_config(profile)
> self._read_user_config(locations_manager.abs_user_config)
>
> def _read_user_config(self, abs_user_config):
> diff --git a/man/portage.5 b/man/portage.5
> index d7b2063e0fc2..787fc18e1a9f 100644
> --- a/man/portage.5
> +++ b/man/portage.5
> @@ -26,6 +26,7 @@ packages.build
> package.accept_keywords
> package.bashrc
> package.keywords
> +package.license
> package.mask
> package.provided
> package.unmask
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 3/4] tests/test_config: Refactor LicenseManager testing to test multiple configurations
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 3/4] tests/test_config: Refactor LicenseManager testing to test multiple configurations Louis Chauvet
@ 2025-12-18 1:27 ` Sam James
0 siblings, 0 replies; 13+ messages in thread
From: Sam James @ 2025-12-18 1:27 UTC (permalink / raw
To: Louis Chauvet; +Cc: gentoo-portage-dev, thomas.petazzoni
Louis Chauvet <louis.chauvet@bootlin.com> writes:
> In order to easly test per-profile per-package license unmasking, extract
> common code from testLicenseManager.
Reviewed-by: Sam James <sam@gentoo.org>
>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
> lib/portage/tests/ebuild/test_config.py | 181 ++++++++++++++++----------------
> 1 file changed, 88 insertions(+), 93 deletions(-)
>
> diff --git a/lib/portage/tests/ebuild/test_config.py b/lib/portage/tests/ebuild/test_config.py
> index 83046a7dc97b..b36073504b11 100644
> --- a/lib/portage/tests/ebuild/test_config.py
> +++ b/lib/portage/tests/ebuild/test_config.py
> @@ -83,16 +83,94 @@ class ConfigTestCase(TestCase):
> finally:
> playground.cleanup()
>
> + _testLicenseManagerPackageLicense = (
> + "dev-libs/* TEST",
> + "dev-libs/A -TEST2",
> + "=dev-libs/A-2 TEST3 @TEST",
> + "*/* @EULA TEST2",
> + "=dev-libs/C-1 *",
> + "=dev-libs/C-2 -*",
> + )
> +
> + def _testLicenseManager(self, lic_man):
> + self.assertEqual(lic_man._accept_license_str, None)
> + self.assertEqual(lic_man._accept_license, None)
> + self.assertEqual(lic_man._license_groups, {"EULA": frozenset(["TEST"])})
> + self.assertEqual(lic_man._undef_lic_groups, {"TEST"})
> +
> + self.assertEqual(lic_man.extract_global_changes(), "TEST TEST2")
> + self.assertEqual(lic_man.extract_global_changes(), "")
> +
> + lic_man.set_accept_license_str("TEST TEST2")
> + self.assertEqual(
> + lic_man._getPkgAcceptLicense("dev-libs/B-1", "0", None),
> + ["TEST", "TEST2", "TEST"],
> + )
> + self.assertEqual(
> + lic_man._getPkgAcceptLicense("dev-libs/A-1", "0", None),
> + ["TEST", "TEST2", "TEST", "-TEST2"],
> + )
> + self.assertEqual(
> + lic_man._getPkgAcceptLicense("dev-libs/A-2", "0", None),
> + ["TEST", "TEST2", "TEST", "-TEST2", "TEST3", "@TEST"],
> + )
> +
> + self.assertEqual(
> + lic_man.get_prunned_accept_license("dev-libs/B-1", [], "TEST", "0", None),
> + "TEST",
> + )
> + self.assertEqual(
> + lic_man.get_prunned_accept_license("dev-libs/A-1", [], "-TEST2", "0", None),
> + "",
> + )
> + self.assertEqual(
> + lic_man.get_prunned_accept_license(
> + "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
> + ),
> + "TEST",
> + )
> + self.assertEqual(
> + lic_man.get_prunned_accept_license("dev-libs/C-1", [], "TEST5", "0", None),
> + "TEST5",
> + )
> + self.assertEqual(
> + lic_man.get_prunned_accept_license("dev-libs/C-2", [], "TEST2", "0", None),
> + "",
> + )
> +
> + self.assertEqual(
> + lic_man.getMissingLicenses("dev-libs/B-1", [], "TEST", "0", None), []
> + )
> + self.assertEqual(
> + lic_man.getMissingLicenses("dev-libs/A-1", [], "-TEST2", "0", None),
> + ["-TEST2"],
> + )
> + self.assertEqual(
> + lic_man.getMissingLicenses(
> + "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
> + ),
> + [],
> + )
> + self.assertEqual(
> + lic_man.getMissingLicenses(
> + "dev-libs/A-3", [], "|| ( TEST2 || ( TEST3 TEST4 ) )", "0", None
> + ),
> + ["TEST2", "TEST3", "TEST4"],
> + )
> + self.assertEqual(
> + lic_man.getMissingLicenses("dev-libs/C-1", [], "TEST5", "0", None), []
> + )
> + self.assertEqual(
> + lic_man.getMissingLicenses("dev-libs/C-2", [], "TEST2", "0", None),
> + ["TEST2"],
> + )
> + self.assertEqual(
> + lic_man.getMissingLicenses("dev-libs/D-1", [], "", "0", None), []
> + )
> +
> def testLicenseManager(self):
> user_config = {
> - "package.license": (
> - "dev-libs/* TEST",
> - "dev-libs/A -TEST2",
> - "=dev-libs/A-2 TEST3 @TEST",
> - "*/* @EULA TEST2",
> - "=dev-libs/C-1 *",
> - "=dev-libs/C-2 -*",
> - ),
> + "package.license": self._testLicenseManagerPackageLicense,
> }
>
> playground = ResolverPlayground(user_config=user_config)
> @@ -100,92 +178,9 @@ class ConfigTestCase(TestCase):
> try:
> portage.util.noiselimit = -2
>
> - pkg_license = os.path.join(playground.eroot, "etc", "portage")
> -
> - lic_man = LicenseManager(settings._locations_manager, pkg_license)
> -
> - self.assertEqual(lic_man._accept_license_str, None)
> - self.assertEqual(lic_man._accept_license, None)
> - self.assertEqual(lic_man._license_groups, {"EULA": frozenset(["TEST"])})
> - self.assertEqual(lic_man._undef_lic_groups, {"TEST"})
> -
> - self.assertEqual(lic_man.extract_global_changes(), "TEST TEST2")
> - self.assertEqual(lic_man.extract_global_changes(), "")
> -
> - lic_man.set_accept_license_str("TEST TEST2")
> - self.assertEqual(
> - lic_man._getPkgAcceptLicense("dev-libs/B-1", "0", None),
> - ["TEST", "TEST2", "TEST"],
> - )
> - self.assertEqual(
> - lic_man._getPkgAcceptLicense("dev-libs/A-1", "0", None),
> - ["TEST", "TEST2", "TEST", "-TEST2"],
> - )
> - self.assertEqual(
> - lic_man._getPkgAcceptLicense("dev-libs/A-2", "0", None),
> - ["TEST", "TEST2", "TEST", "-TEST2", "TEST3", "@TEST"],
> - )
> -
> - self.assertEqual(
> - lic_man.get_prunned_accept_license(
> - "dev-libs/B-1", [], "TEST", "0", None
> - ),
> - "TEST",
> - )
> - self.assertEqual(
> - lic_man.get_prunned_accept_license(
> - "dev-libs/A-1", [], "-TEST2", "0", None
> - ),
> - "",
> - )
> - self.assertEqual(
> - lic_man.get_prunned_accept_license(
> - "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
> - ),
> - "TEST",
> - )
> - self.assertEqual(
> - lic_man.get_prunned_accept_license(
> - "dev-libs/C-1", [], "TEST5", "0", None
> - ),
> - "TEST5",
> - )
> - self.assertEqual(
> - lic_man.get_prunned_accept_license(
> - "dev-libs/C-2", [], "TEST2", "0", None
> - ),
> - "",
> - )
> + lic_man = LicenseManager(settings._locations_manager)
> + self._testLicenseManager(lic_man)
>
> - self.assertEqual(
> - lic_man.getMissingLicenses("dev-libs/B-1", [], "TEST", "0", None), []
> - )
> - self.assertEqual(
> - lic_man.getMissingLicenses("dev-libs/A-1", [], "-TEST2", "0", None),
> - ["-TEST2"],
> - )
> - self.assertEqual(
> - lic_man.getMissingLicenses(
> - "dev-libs/A-2", [], "|| ( TEST TEST2 )", "0", None
> - ),
> - [],
> - )
> - self.assertEqual(
> - lic_man.getMissingLicenses(
> - "dev-libs/A-3", [], "|| ( TEST2 || ( TEST3 TEST4 ) )", "0", None
> - ),
> - ["TEST2", "TEST3", "TEST4"],
> - )
> - self.assertEqual(
> - lic_man.getMissingLicenses("dev-libs/C-1", [], "TEST5", "0", None), []
> - )
> - self.assertEqual(
> - lic_man.getMissingLicenses("dev-libs/C-2", [], "TEST2", "0", None),
> - ["TEST2"],
> - )
> - self.assertEqual(
> - lic_man.getMissingLicenses("dev-libs/D-1", [], "", "0", None), []
> - )
> finally:
> portage.util.noiselimit = 0
> playground.cleanup()
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 4/4] tests/test_config: Add test for package.license in profiles
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 4/4] tests/test_config: Add test for package.license in profiles Louis Chauvet
@ 2025-12-18 1:28 ` Sam James
0 siblings, 0 replies; 13+ messages in thread
From: Sam James @ 2025-12-18 1:28 UTC (permalink / raw
To: Louis Chauvet; +Cc: gentoo-portage-dev, thomas.petazzoni
Louis Chauvet <louis.chauvet@bootlin.com> writes:
> Now package.license can be read from profiles, add two tests to ensure that
> user and profile configuration are properly read.
Reviewed-by: Sam James <sam@gentoo.org>
>
> Signed-off-by: Louis Chauvet <louis.chauvet@bootlin.com>
> ---
> lib/portage/tests/ebuild/test_config.py | 37 +++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/lib/portage/tests/ebuild/test_config.py b/lib/portage/tests/ebuild/test_config.py
> index b36073504b11..43940987254b 100644
> --- a/lib/portage/tests/ebuild/test_config.py
> +++ b/lib/portage/tests/ebuild/test_config.py
> @@ -185,6 +185,43 @@ class ConfigTestCase(TestCase):
> portage.util.noiselimit = 0
> playground.cleanup()
>
> + def testLicenseManagerProfile(self):
> + profile_config = {
> + "package.license": self._testLicenseManagerPackageLicense,
> + }
> +
> + playground = ResolverPlayground(profile=profile_config)
> + settings = config(clone=playground.settings)
> + try:
> + portage.util.noiselimit = -2
> +
> + lic_man = LicenseManager(settings._locations_manager)
> + self._testLicenseManager(lic_man)
> +
> + finally:
> + portage.util.noiselimit = 0
> + playground.cleanup()
> +
> + def testLicenseManagerMixed(self):
> + profile_config = {
> + "package.license": self._testLicenseManagerPackageLicense[:4],
> + }
> + user_config = {
> + "package.license": self._testLicenseManagerPackageLicense[4:],
> + }
> +
> + playground = ResolverPlayground(user_config=user_config, profile=profile_config)
> + settings = config(clone=playground.settings)
> + try:
> + portage.util.noiselimit = -2
> +
> + lic_man = LicenseManager(settings._locations_manager)
> + self._testLicenseManager(lic_man)
> +
> + finally:
> + portage.util.noiselimit = 0
> + playground.cleanup()
> +
> def testPackageMaskOrder(self):
> ebuilds = {
> "dev-libs/A-1": {},
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles
2025-12-17 11:10 ` Louis Chauvet
@ 2025-12-18 1:28 ` Sam James
0 siblings, 0 replies; 13+ messages in thread
From: Sam James @ 2025-12-18 1:28 UTC (permalink / raw
To: Louis Chauvet; +Cc: Ulrich Müller, gentoo-portage-dev, thomas.petazzoni
Louis Chauvet <louis.chauvet@bootlin.com> writes:
> On 12/17/25 10:33, Ulrich Müller wrote:
>>>>>>> On Wed, 17 Dec 2025, Louis Chauvet wrote:
>>
>>> Currently profiles does not allow using per-package license unmasking.
>>> The only solution is the LICENSE variable, which apply to all the packages.
>> What would be the application for this? I understand package.license
>> in user configuration, but why would we ever want to unmask nonfree
>> per-package licenses in profiles?
Profiles aren't just for the type we use in ::gentoo. They are often
used for custom deployments to different machine types in a fleet.
>
> My goal is to create my own custom profile to use the same set of
> packages, version, use between my laptop and my desktop.
>
> I have some non-free packages (linux-firmware, Saleae,
> intel-microcode), so for me that make sense to have a package.license
> file in the profile.
I think it's a reasonable usecase indeed.
>
> For information, I also opened a pull request on Codeberg [1] because
> I wasn’t sure if the mailing list was active.
>
> [1]:https://codeberg.org/gentoo/portage/pulls/1
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-12-18 1:29 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-17 7:10 [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Louis Chauvet
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 1/4] lib/portage/package/ebuild/_config/LicenseManager.py: Use location_manager instead of paths Louis Chauvet
2025-12-18 1:26 ` Sam James
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 2/4] lib/portage/package/ebuild/_config/LicenseManager.py: Read per-profile package.license Louis Chauvet
2025-12-18 1:27 ` [gentoo-portage-dev] " Sam James
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 3/4] tests/test_config: Refactor LicenseManager testing to test multiple configurations Louis Chauvet
2025-12-18 1:27 ` Sam James
2025-12-17 7:10 ` [gentoo-portage-dev] [PATCH RESEND 4/4] tests/test_config: Add test for package.license in profiles Louis Chauvet
2025-12-18 1:28 ` Sam James
2025-12-17 9:33 ` [gentoo-portage-dev] [PATCH RESEND 0/4] Add package.license support to profiles Ulrich Müller
2025-12-17 10:15 ` Michael Orlitzky
2025-12-17 11:10 ` Louis Chauvet
2025-12-18 1:28 ` Sam James
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox