Files
nixpkgs/lib/licenses/helpers.nix

188 lines
4.7 KiB
Nix

{ lib }:
let
inherit (lib) all any elem;
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
evaluateSubProperty license.license && evaluateSubProperty 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.
# Example
```nix
evaluateProperty (x: x.free) true (with lib.licenses; AND [ ncsa (WITH asl20 llvm-exception) ])
```
# Type
```
evaluateProperty :: Function -> Bool -> AttrSet -> Bool
```
# Arguments
- [predicate] checks for each license included in the license expression
- [permissive] whether to apply checks permissive or reciprocal
- [license] license expression to check
*/
evaluateProperty =
predicate: permissive:
let
OR = if permissive then any else all;
AND = if permissive then all else any;
evaluateComplexProperty = handleComplexProperty (evaluateProperty predicate permissive) AND OR;
in
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 any else all;
AND = if permissive then all else 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.
# Example
```nix
isFree (with lib.licenses; (AND [ ncsa (WITH asl20 llvm-exception) ]))
=> true
```
# Type
```
isFree :: AttrSet -> Bool
```
# Arguments
- [license] License expression to check if free
*/
isFree = evaluateNamedProperty "free" true;
/**
Check whether a license expression is redistributable.
# Example
```nix
isRedistributable (with lib.licenses; (AND [ ncsa (WITH asl20 llvm-exception) ]))
=> true
```
# Type
```
isRedistributable :: AttrSet -> Bool
```
# Arguments
- [license] License expression to check if redistributable
*/
isRedistributable = evaluateNamedProperty "redistributable" true;
/**
Check whether any of the given licenses is required in the license expression.
# Example
```nix
containsLicenses [ lib.licenses.asl20 ] (with lib.licenses; (AND [ ncsa (WITH asl20 llvm-exception) ]))
=> true
```
# Type
```
containsLicenses :: List -> AttrSet -> Bool
```
# Arguments
- [licenses] List of licenses to look
- [license] License expression to check
*/
containsLicenses = licenses: evaluateProperty (x: elem x licenses) false;
/**
Convert a license expression to an SPDX license expression string.
# Example
```nix
toSPDX (with lib.licenses; AND [ ncsa (WITH asl20 llvm-exception) ])
=> "NCSA AND (Apache-2.0 WITH LLVM-exception)"
```
# Type
```
toSPDX :: AttrSet -> String
```
# Arguments
- [license] License expression which to convert to spdx expression
*/
toSPDX =
license:
let
mkBracket =
x:
if x.licenseType == "compound" || x.licenseType == "exception" then "(${toSPDX x})" else toSPDX x;
in
if license.licenseType == "simple" then
license.spdxId or "LicenseRef-nixos-${license.shortName}"
else if license.licenseType == "compound" then
lib.concatMapStringsSep " ${license.operator} " (x: mkBracket x) license.licenses
else if license.licenseType == "exception" then
"${mkBracket license.license} ${license.operator} ${mkBracket license.exception}"
else if license.licenseType == "plus" then
"${mkBracket license.license}${license.operator}"
else
throw "Unknown license type";
}