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.