From 22fcb80812e352419b26e1063f3bf27fd61098a0 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:03:20 -0400 Subject: [PATCH 1/5] lib.licenses: only define OR and AND once --- lib/licenses/helpers.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/licenses/helpers.nix b/lib/licenses/helpers.nix index b234515284f8..ea02d2d2a3bb 100644 --- a/lib/licenses/helpers.nix +++ b/lib/licenses/helpers.nix @@ -21,11 +21,12 @@ rec { - [license] license expression to check */ evaluateProperty = - predicate: permissive: license: + predicate: permissive: let OR = if permissive then lib.any else lib.all; AND = if permissive then lib.all else lib.any; in + license: if license.licenseType == "simple" then predicate license else if license.licenseType == "compound" then From 9e48db8d39e9d23f64b8e5643d05aa497e56e0af Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:03:54 -0400 Subject: [PATCH 2/5] lib.licenses: prevent subcalls for non-simple licenses --- lib/licenses/helpers.nix | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/licenses/helpers.nix b/lib/licenses/helpers.nix index ea02d2d2a3bb..f6deab63614d 100644 --- a/lib/licenses/helpers.nix +++ b/lib/licenses/helpers.nix @@ -25,24 +25,25 @@ rec { let OR = if permissive then lib.any else lib.all; AND = if permissive then lib.all else lib.any; + evaluateSubProperty = evaluateProperty predicate permissive; in license: if license.licenseType == "simple" then predicate license else if license.licenseType == "compound" then if license.operator == "OR" then - OR (x: evaluateProperty predicate permissive x) license.licenses + OR evaluateSubProperty license.licenses else if license.operator == "AND" then - AND (x: evaluateProperty predicate permissive x) license.licenses + AND evaluateSubProperty license.licenses else throw "Unknown license operator" else if license.licenseType == "exception" then - AND (x: evaluateProperty predicate permissive x) [ + AND evaluateSubProperty [ license.license license.exception ] else if license.licenseType == "plus" then - evaluateProperty predicate permissive license.license + evaluateSubProperty license.license else throw "Unknown license type or legacy license"; From 64e42fb8b1ec48c8565fe9bd6369827ded6a2392 Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:07:49 -0400 Subject: [PATCH 3/5] lib.licenses: add evaluateNamedProperty for quickly checking subattributes --- lib/licenses/helpers.nix | 77 +++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 21 deletions(-) diff --git a/lib/licenses/helpers.nix b/lib/licenses/helpers.nix index f6deab63614d..c64926284454 100644 --- a/lib/licenses/helpers.nix +++ b/lib/licenses/helpers.nix @@ -1,4 +1,25 @@ { lib }: + +let + handleComplexProperty = + evaluateSubProperty: AND: OR: license: + if license.licenseType == "compound" then + if license.operator == "OR" then + OR evaluateSubProperty license.licenses + else if license.operator == "AND" then + AND evaluateSubProperty license.licenses + else + throw "Unknown license operator" + else if license.licenseType == "exception" then + AND evaluateSubProperty [ + license.license + license.exception + ] + else if license.licenseType == "plus" then + evaluateSubProperty license.license + else + throw "Unknown license type or legacy license"; +in rec { /** Evaluate a license expression for a given predicate. @@ -25,27 +46,41 @@ rec { let OR = if permissive then lib.any else lib.all; AND = if permissive then lib.all else lib.any; - evaluateSubProperty = evaluateProperty predicate permissive; + evaluateComplexProperty = handleComplexProperty (evaluateProperty predicate permissive) AND OR; in license: - if license.licenseType == "simple" then - predicate license - else if license.licenseType == "compound" then - if license.operator == "OR" then - OR evaluateSubProperty license.licenses - else if license.operator == "AND" then - AND evaluateSubProperty license.licenses - else - throw "Unknown license operator" - else if license.licenseType == "exception" then - AND evaluateSubProperty [ - license.license - license.exception - ] - else if license.licenseType == "plus" then - evaluateSubProperty license.license - else - throw "Unknown license type or legacy license"; + if license.licenseType == "simple" then predicate license else evaluateComplexProperty license; + + /** + Evaluate a license expression for a given property name. The property must + be defined as a boolean attribute of all licenses passed. + + # Example + + ```nix + evaluateNamedProperty "deprecated" true (with lib.licenses; AND [ ncsa (WITH asl20 llvm-exception) ]) + ``` + # Type + + ``` + evaluateProperty :: String -> Bool -> AttrSet -> Bool + ``` + + # Arguments + + - [name] name of the attribute to check + - [permissive] whether to apply checks permissive or reciprocal + - [license] license expression to check + */ + evaluateNamedProperty = + name: permissive: + let + OR = if permissive then lib.any else lib.all; + AND = if permissive then lib.all else lib.any; + evaluateComplexProperty = handleComplexProperty (evaluateNamedProperty name permissive) AND OR; + in + license: + if license.licenseType == "simple" then license.${name} else evaluateComplexProperty license; /** Check whether a license expression is free. @@ -67,7 +102,7 @@ rec { - [license] License expression to check if free */ - isFree = evaluateProperty (x: x.free) true; + isFree = evaluateNamedProperty "free" true; /** Check whether a license expression is redistributable. @@ -89,7 +124,7 @@ rec { - [license] License expression to check if redistributable */ - isRedistributable = evaluateProperty (x: x.redistributable) true; + isRedistributable = evaluateNamedProperty "redistributable" true; /** Check whether any of the given licenses is required in the license expression. From 1883329515168a1c9db852f046a62cf867f534dc Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:20:37 -0400 Subject: [PATCH 4/5] lib.licenses: use && for exception licenses Seems preferable to iterating over a two-element list. licenseType.exception is only used by lib.licenses.WITH, which I don't see any usage of in tree - but thought I might as well. --- lib/licenses/helpers.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/licenses/helpers.nix b/lib/licenses/helpers.nix index c64926284454..b4af85b90113 100644 --- a/lib/licenses/helpers.nix +++ b/lib/licenses/helpers.nix @@ -11,10 +11,7 @@ let else throw "Unknown license operator" else if license.licenseType == "exception" then - AND evaluateSubProperty [ - license.license - license.exception - ] + evaluateSubProperty license.license && evaluateSubProperty license.exception else if license.licenseType == "plus" then evaluateSubProperty license.license else From 32a19032292ff818fdc30b3ac8dcfe283f04dd4e Mon Sep 17 00:00:00 2001 From: Eman Resu <78693624+quatquatt@users.noreply.github.com> Date: Tue, 19 May 2026 23:05:56 -0400 Subject: [PATCH 5/5] lib.licenses: inherit lib functions into global scope --- lib/licenses/helpers.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/licenses/helpers.nix b/lib/licenses/helpers.nix index b4af85b90113..37721489f77a 100644 --- a/lib/licenses/helpers.nix +++ b/lib/licenses/helpers.nix @@ -1,6 +1,7 @@ { lib }: let + inherit (lib) all any elem; handleComplexProperty = evaluateSubProperty: AND: OR: license: if license.licenseType == "compound" then @@ -41,8 +42,8 @@ rec { evaluateProperty = predicate: permissive: let - OR = if permissive then lib.any else lib.all; - AND = if permissive then lib.all else lib.any; + OR = if permissive then any else all; + AND = if permissive then all else any; evaluateComplexProperty = handleComplexProperty (evaluateProperty predicate permissive) AND OR; in license: @@ -72,8 +73,8 @@ rec { evaluateNamedProperty = name: permissive: let - OR = if permissive then lib.any else lib.all; - AND = if permissive then lib.all else lib.any; + OR = if permissive then any else all; + AND = if permissive then all else any; evaluateComplexProperty = handleComplexProperty (evaluateNamedProperty name permissive) AND OR; in license: @@ -144,7 +145,7 @@ rec { - [licenses] List of licenses to look - [license] License expression to check */ - containsLicenses = licenses: evaluateProperty (x: lib.lists.elem x licenses) false; + containsLicenses = licenses: evaluateProperty (x: elem x licenses) false; /** Convert a license expression to an SPDX license expression string.