2020-04-24 23:36:52 +00:00
|
|
|
|
# Checks derivation meta and attrs for problems (like brokenness,
|
|
|
|
|
# licenses, etc).
|
|
|
|
|
|
|
|
|
|
{ lib, config, hostPlatform }:
|
|
|
|
|
|
|
|
|
|
let
|
|
|
|
|
# If we're in hydra, we can dispense with the more verbose error
|
|
|
|
|
# messages and make problems easier to spot.
|
|
|
|
|
inHydra = config.inHydra or false;
|
2022-04-27 09:35:20 +00:00
|
|
|
|
# Allow the user to opt-into additional warnings, e.g.
|
|
|
|
|
# import <nixpkgs> { config = { showDerivationWarnings = [ "maintainerless" ]; }; }
|
|
|
|
|
showWarnings = config.showDerivationWarnings;
|
|
|
|
|
|
2020-04-24 23:36:52 +00:00
|
|
|
|
getName = attrs: attrs.name or ("${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}");
|
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
allowUnfree = config.allowUnfree
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|| builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1";
|
|
|
|
|
|
2022-10-21 18:38:19 +00:00
|
|
|
|
allowNonSource = let
|
|
|
|
|
envVar = builtins.getEnv "NIXPKGS_ALLOW_NONSOURCE";
|
|
|
|
|
in if envVar != ""
|
|
|
|
|
then envVar != "0"
|
|
|
|
|
else config.allowNonSource or true;
|
2022-06-16 17:23:12 +00:00
|
|
|
|
|
2021-02-24 18:30:23 +00:00
|
|
|
|
allowlist = config.allowlistedLicenses or config.whitelistedLicenses or [];
|
|
|
|
|
blocklist = config.blocklistedLicenses or config.blacklistedLicenses or [];
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
|
|
areLicenseListsValid =
|
2021-02-24 18:30:23 +00:00
|
|
|
|
if lib.mutuallyExclusive allowlist blocklist then
|
2022-03-10 19:12:11 +00:00
|
|
|
|
true
|
2020-04-24 23:36:52 +00:00
|
|
|
|
else
|
2021-02-24 18:30:23 +00:00
|
|
|
|
throw "allowlistedLicenses and blocklistedLicenses are not mutually exclusive.";
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
|
|
hasLicense = attrs:
|
|
|
|
|
attrs ? meta.license;
|
|
|
|
|
|
2021-02-24 18:30:23 +00:00
|
|
|
|
hasAllowlistedLicense = assert areLicenseListsValid; attrs:
|
|
|
|
|
hasLicense attrs && lib.lists.any (l: builtins.elem l allowlist) (lib.lists.toList attrs.meta.license);
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
2021-02-24 18:30:23 +00:00
|
|
|
|
hasBlocklistedLicense = assert areLicenseListsValid; attrs:
|
|
|
|
|
hasLicense attrs && lib.lists.any (l: builtins.elem l blocklist) (lib.lists.toList attrs.meta.license);
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
allowBroken = config.allowBroken
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|| builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
|
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
allowUnsupportedSystem = config.allowUnsupportedSystem
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|| builtins.getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1";
|
|
|
|
|
|
|
|
|
|
isUnfree = licenses: lib.lists.any (l: !l.free or true) licenses;
|
|
|
|
|
|
2020-11-30 08:33:03 +00:00
|
|
|
|
hasUnfreeLicense = attrs:
|
|
|
|
|
hasLicense attrs &&
|
|
|
|
|
isUnfree (lib.lists.toList attrs.meta.license);
|
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
hasNoMaintainers = attrs:
|
|
|
|
|
attrs ? meta.maintainers && (lib.length attrs.meta.maintainers) == 0;
|
|
|
|
|
|
2020-11-30 08:33:03 +00:00
|
|
|
|
isMarkedBroken = attrs: attrs.meta.broken or false;
|
|
|
|
|
|
2023-01-11 07:51:40 +00:00
|
|
|
|
hasUnsupportedPlatform =
|
|
|
|
|
pkg: !(lib.meta.availableOn hostPlatform pkg);
|
2020-11-30 08:33:03 +00:00
|
|
|
|
|
|
|
|
|
isMarkedInsecure = attrs: (attrs.meta.knownVulnerabilities or []) != [];
|
|
|
|
|
|
2020-04-24 23:36:52 +00:00
|
|
|
|
# Alow granular checks to allow only some unfree packages
|
|
|
|
|
# Example:
|
|
|
|
|
# {pkgs, ...}:
|
|
|
|
|
# {
|
|
|
|
|
# allowUnfree = false;
|
2021-02-13 14:23:35 +00:00
|
|
|
|
# allowUnfreePredicate = (x: pkgs.lib.hasPrefix "vscode" x.name);
|
2020-04-24 23:36:52 +00:00
|
|
|
|
# }
|
|
|
|
|
allowUnfreePredicate = config.allowUnfreePredicate or (x: false);
|
|
|
|
|
|
|
|
|
|
# Check whether unfree packages are allowed and if not, whether the
|
2022-12-28 21:21:41 +00:00
|
|
|
|
# package has an unfree license and is not explicitly allowed by the
|
2020-04-24 23:36:52 +00:00
|
|
|
|
# `allowUnfreePredicate` function.
|
|
|
|
|
hasDeniedUnfreeLicense = attrs:
|
2020-11-30 08:33:03 +00:00
|
|
|
|
hasUnfreeLicense attrs &&
|
2020-04-24 23:36:52 +00:00
|
|
|
|
!allowUnfree &&
|
|
|
|
|
!allowUnfreePredicate attrs;
|
|
|
|
|
|
|
|
|
|
allowInsecureDefaultPredicate = x: builtins.elem (getName x) (config.permittedInsecurePackages or []);
|
|
|
|
|
allowInsecurePredicate = x: (config.allowInsecurePredicate or allowInsecureDefaultPredicate) x;
|
|
|
|
|
|
|
|
|
|
hasAllowedInsecure = attrs:
|
2020-11-30 08:33:03 +00:00
|
|
|
|
!(isMarkedInsecure attrs) ||
|
2020-04-24 23:36:52 +00:00
|
|
|
|
allowInsecurePredicate attrs ||
|
|
|
|
|
builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
|
|
|
|
|
|
2022-06-16 17:23:12 +00:00
|
|
|
|
|
|
|
|
|
isNonSource = sourceTypes: lib.lists.any (t: !t.isSource) sourceTypes;
|
|
|
|
|
|
|
|
|
|
hasNonSourceProvenance = attrs:
|
|
|
|
|
(attrs ? meta.sourceProvenance) &&
|
2023-01-11 07:51:40 +00:00
|
|
|
|
isNonSource attrs.meta.sourceProvenance;
|
2022-06-16 17:23:12 +00:00
|
|
|
|
|
|
|
|
|
# Allow granular checks to allow only some non-source-built packages
|
|
|
|
|
# Example:
|
|
|
|
|
# { pkgs, ... }:
|
|
|
|
|
# {
|
|
|
|
|
# allowNonSource = false;
|
2023-01-11 07:51:40 +00:00
|
|
|
|
# allowNonSourcePredicate = with pkgs.lib.lists; pkg: !(any (p: !p.isSource && p != lib.sourceTypes.binaryFirmware) pkg.meta.sourceProvenance);
|
2022-06-16 17:23:12 +00:00
|
|
|
|
# }
|
|
|
|
|
allowNonSourcePredicate = config.allowNonSourcePredicate or (x: false);
|
|
|
|
|
|
|
|
|
|
# Check whether non-source packages are allowed and if not, whether the
|
|
|
|
|
# package has non-source provenance and is not explicitly allowed by the
|
|
|
|
|
# `allowNonSourcePredicate` function.
|
|
|
|
|
hasDeniedNonSourceProvenance = attrs:
|
|
|
|
|
hasNonSourceProvenance attrs &&
|
|
|
|
|
!allowNonSource &&
|
|
|
|
|
!allowNonSourcePredicate attrs;
|
|
|
|
|
|
|
|
|
|
showLicenseOrSourceType = value: toString (map (v: v.shortName or "unknown") (lib.lists.toList value));
|
|
|
|
|
showLicense = showLicenseOrSourceType;
|
|
|
|
|
showSourceType = showLicenseOrSourceType;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
|
|
pos_str = meta: meta.position or "«unknown-file»";
|
|
|
|
|
|
|
|
|
|
remediation = {
|
2022-06-16 17:23:12 +00:00
|
|
|
|
unfree = remediate_allowlist "Unfree" (remediate_predicate "allowUnfreePredicate");
|
|
|
|
|
non-source = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate");
|
2021-02-24 18:30:23 +00:00
|
|
|
|
broken = remediate_allowlist "Broken" (x: "");
|
|
|
|
|
unsupported = remediate_allowlist "UnsupportedSystem" (x: "");
|
|
|
|
|
blocklisted = x: "";
|
2020-04-24 23:36:52 +00:00
|
|
|
|
insecure = remediate_insecure;
|
|
|
|
|
broken-outputs = remediateOutputsToInstall;
|
|
|
|
|
unknown-meta = x: "";
|
2022-04-27 09:35:20 +00:00
|
|
|
|
maintainerless = x: "";
|
2020-04-24 23:36:52 +00:00
|
|
|
|
};
|
2020-11-06 00:33:48 +00:00
|
|
|
|
remediation_env_var = allow_attr: {
|
|
|
|
|
Unfree = "NIXPKGS_ALLOW_UNFREE";
|
|
|
|
|
Broken = "NIXPKGS_ALLOW_BROKEN";
|
|
|
|
|
UnsupportedSystem = "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM";
|
2022-06-16 17:23:12 +00:00
|
|
|
|
NonSource = "NIXPKGS_ALLOW_NONSOURCE";
|
2020-11-06 00:33:48 +00:00
|
|
|
|
}.${allow_attr};
|
|
|
|
|
remediation_phrase = allow_attr: {
|
|
|
|
|
Unfree = "unfree packages";
|
|
|
|
|
Broken = "broken packages";
|
|
|
|
|
UnsupportedSystem = "packages that are unsupported for this system";
|
2022-06-16 17:23:12 +00:00
|
|
|
|
NonSource = "packages not built from source";
|
2020-11-06 00:33:48 +00:00
|
|
|
|
}.${allow_attr};
|
2022-06-16 17:23:12 +00:00
|
|
|
|
remediate_predicate = predicateConfigAttr: attrs:
|
2020-11-12 09:05:59 +00:00
|
|
|
|
''
|
|
|
|
|
|
2021-02-24 18:30:23 +00:00
|
|
|
|
Alternatively you can configure a predicate to allow specific packages:
|
2022-06-16 17:23:12 +00:00
|
|
|
|
{ nixpkgs.config.${predicateConfigAttr} = pkg: builtins.elem (lib.getName pkg) [
|
2020-11-12 09:05:59 +00:00
|
|
|
|
"${lib.getName attrs}"
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
'';
|
|
|
|
|
|
2022-02-10 20:34:41 +00:00
|
|
|
|
# flakeNote will be printed in the remediation messages below.
|
|
|
|
|
flakeNote = "
|
|
|
|
|
Note: For `nix shell`, `nix build`, `nix develop` or any other Nix 2.4+
|
|
|
|
|
(Flake) command, `--impure` must be passed in order to read this
|
|
|
|
|
environment variable.
|
|
|
|
|
";
|
|
|
|
|
|
2021-02-24 18:30:23 +00:00
|
|
|
|
remediate_allowlist = allow_attr: rebuild_amendment: attrs:
|
2020-04-24 23:36:52 +00:00
|
|
|
|
''
|
2020-11-06 00:33:48 +00:00
|
|
|
|
a) To temporarily allow ${remediation_phrase allow_attr}, you can use an environment variable
|
|
|
|
|
for a single invocation of the nix tools.
|
|
|
|
|
|
|
|
|
|
$ export ${remediation_env_var allow_attr}=1
|
2022-02-10 20:34:41 +00:00
|
|
|
|
${flakeNote}
|
2020-11-06 00:33:48 +00:00
|
|
|
|
b) For `nixos-rebuild` you can set
|
2020-04-24 23:36:52 +00:00
|
|
|
|
{ nixpkgs.config.allow${allow_attr} = true; }
|
|
|
|
|
in configuration.nix to override this.
|
2020-11-12 09:05:59 +00:00
|
|
|
|
${rebuild_amendment attrs}
|
2020-11-06 00:33:48 +00:00
|
|
|
|
c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
|
2020-04-24 23:36:52 +00:00
|
|
|
|
{ allow${allow_attr} = true; }
|
|
|
|
|
to ~/.config/nixpkgs/config.nix.
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
remediate_insecure = attrs:
|
|
|
|
|
''
|
|
|
|
|
|
|
|
|
|
Known issues:
|
|
|
|
|
'' + (lib.concatStrings (map (issue: " - ${issue}\n") attrs.meta.knownVulnerabilities)) + ''
|
|
|
|
|
|
2021-02-24 18:30:23 +00:00
|
|
|
|
You can install it anyway by allowing this package, using the
|
2020-04-24 23:36:52 +00:00
|
|
|
|
following methods:
|
|
|
|
|
|
2020-06-18 07:06:33 +00:00
|
|
|
|
a) To temporarily allow all insecure packages, you can use an environment
|
|
|
|
|
variable for a single invocation of the nix tools:
|
|
|
|
|
|
|
|
|
|
$ export NIXPKGS_ALLOW_INSECURE=1
|
2022-02-10 20:34:41 +00:00
|
|
|
|
${flakeNote}
|
2020-06-18 07:06:33 +00:00
|
|
|
|
b) for `nixos-rebuild` you can add ‘${getName attrs}’ to
|
2020-04-24 23:36:52 +00:00
|
|
|
|
`nixpkgs.config.permittedInsecurePackages` in the configuration.nix,
|
|
|
|
|
like so:
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
nixpkgs.config.permittedInsecurePackages = [
|
|
|
|
|
"${getName attrs}"
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-18 07:06:33 +00:00
|
|
|
|
c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
|
|
|
|
|
‘${getName attrs}’ to `permittedInsecurePackages` in
|
|
|
|
|
~/.config/nixpkgs/config.nix, like so:
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
permittedInsecurePackages = [
|
|
|
|
|
"${getName attrs}"
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
remediateOutputsToInstall = attrs: let
|
|
|
|
|
expectedOutputs = attrs.meta.outputsToInstall or [];
|
|
|
|
|
actualOutputs = attrs.outputs or [ "out" ];
|
|
|
|
|
missingOutputs = builtins.filter (output: ! builtins.elem output actualOutputs) expectedOutputs;
|
|
|
|
|
in ''
|
|
|
|
|
The package ${getName attrs} has set meta.outputsToInstall to: ${builtins.concatStringsSep ", " expectedOutputs}
|
|
|
|
|
|
|
|
|
|
however ${getName attrs} only has the outputs: ${builtins.concatStringsSep ", " actualOutputs}
|
|
|
|
|
|
|
|
|
|
and is missing the following ouputs:
|
|
|
|
|
|
|
|
|
|
${lib.concatStrings (builtins.map (output: " - ${output}\n") missingOutputs)}
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
handleEvalIssue = { meta, attrs }: { reason , errormsg ? "" }:
|
|
|
|
|
let
|
|
|
|
|
msg = if inHydra
|
|
|
|
|
then "Failed to evaluate ${getName attrs}: «${reason}»: ${errormsg}"
|
|
|
|
|
else ''
|
|
|
|
|
Package ‘${getName attrs}’ in ${pos_str meta} ${errormsg}, refusing to evaluate.
|
|
|
|
|
|
|
|
|
|
'' + (builtins.getAttr reason remediation) attrs;
|
|
|
|
|
|
|
|
|
|
handler = if config ? handleEvalIssue
|
|
|
|
|
then config.handleEvalIssue reason
|
|
|
|
|
else throw;
|
|
|
|
|
in handler msg;
|
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
handleEvalWarning = { meta, attrs }: { reason , errormsg ? "" }:
|
|
|
|
|
let
|
|
|
|
|
remediationMsg = (builtins.getAttr reason remediation) attrs;
|
|
|
|
|
msg = if inHydra then "Warning while evaluating ${getName attrs}: «${reason}»: ${errormsg}"
|
|
|
|
|
else "Package ${getName attrs} in ${pos_str meta} ${errormsg}, continuing anyway."
|
2023-02-16 17:41:37 +00:00
|
|
|
|
+ (lib.optionalString (remediationMsg != "") "\n${remediationMsg}");
|
2022-04-27 09:35:20 +00:00
|
|
|
|
isEnabled = lib.findFirst (x: x == reason) null showWarnings;
|
|
|
|
|
in if isEnabled != null then builtins.trace msg true else true;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
2023-01-11 07:51:40 +00:00
|
|
|
|
# Deep type-checking. Note that calling `type.check` is not enough: see `lib.mkOptionType`'s documentation.
|
|
|
|
|
# We don't include this in lib for now because this function is flawed: it accepts things like `mkIf true 42`.
|
|
|
|
|
typeCheck = type: value: let
|
|
|
|
|
merged = lib.mergeDefinitions [ ] type [
|
|
|
|
|
{ file = lib.unknownModule; inherit value; }
|
|
|
|
|
];
|
|
|
|
|
eval = builtins.tryEval (builtins.deepSeq merged.mergedValue null);
|
|
|
|
|
in eval.success;
|
2022-09-30 11:47:45 +00:00
|
|
|
|
|
2023-01-11 07:51:40 +00:00
|
|
|
|
# TODO make this into a proper module and use the generic option documentation generation?
|
2020-04-24 23:36:52 +00:00
|
|
|
|
metaTypes = with lib.types; rec {
|
|
|
|
|
# These keys are documented
|
|
|
|
|
description = str;
|
2021-04-26 19:14:03 +00:00
|
|
|
|
mainProgram = str;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
longDescription = str;
|
|
|
|
|
branch = str;
|
|
|
|
|
homepage = either (listOf str) str;
|
|
|
|
|
downloadPage = str;
|
|
|
|
|
changelog = either (listOf str) str;
|
2023-01-11 07:51:40 +00:00
|
|
|
|
license = let
|
|
|
|
|
licenseType = either (attrsOf anything) str; # TODO disallow `str` licenses, use a module
|
|
|
|
|
in either licenseType (listOf licenseType);
|
|
|
|
|
sourceProvenance = listOf lib.types.attrs;
|
|
|
|
|
maintainers = listOf (attrsOf anything); # TODO use the maintainer type from lib/tests/maintainer-module.nix
|
2020-04-24 23:36:52 +00:00
|
|
|
|
priority = int;
|
2023-02-09 11:40:11 +00:00
|
|
|
|
pkgConfigModules = listOf str;
|
2023-01-11 07:51:40 +00:00
|
|
|
|
platforms = listOf (either str (attrsOf anything)); # see lib.meta.platformMatch
|
2020-04-24 23:36:52 +00:00
|
|
|
|
hydraPlatforms = listOf str;
|
|
|
|
|
broken = bool;
|
2020-11-30 08:33:03 +00:00
|
|
|
|
unfree = bool;
|
|
|
|
|
unsupported = bool;
|
|
|
|
|
insecure = bool;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
# TODO: refactor once something like Profpatsch's types-simple will land
|
|
|
|
|
# This is currently dead code due to https://github.com/NixOS/nix/issues/2532
|
|
|
|
|
tests = attrsOf (mkOptionType {
|
|
|
|
|
name = "test";
|
|
|
|
|
check = x: x == {} || ( # Accept {} for tests that are unsupported
|
|
|
|
|
isDerivation x &&
|
|
|
|
|
x ? meta.timeout
|
|
|
|
|
);
|
|
|
|
|
merge = lib.options.mergeOneOption;
|
|
|
|
|
});
|
|
|
|
|
timeout = int;
|
|
|
|
|
|
2022-09-30 11:47:45 +00:00
|
|
|
|
# Needed for Hydra to expose channel tarballs:
|
|
|
|
|
# https://github.com/NixOS/hydra/blob/53335323ae79ca1a42643f58e520b376898ce641/doc/manual/src/jobs.md#meta-fields
|
|
|
|
|
isHydraChannel = bool;
|
|
|
|
|
|
2020-04-24 23:36:52 +00:00
|
|
|
|
# Weirder stuff that doesn't appear in the documentation?
|
2021-08-08 23:34:03 +00:00
|
|
|
|
maxSilent = int;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
knownVulnerabilities = listOf str;
|
|
|
|
|
name = str;
|
|
|
|
|
version = str;
|
|
|
|
|
tag = str;
|
|
|
|
|
executables = listOf str;
|
|
|
|
|
outputsToInstall = listOf str;
|
|
|
|
|
position = str;
|
2022-10-21 18:38:19 +00:00
|
|
|
|
available = unspecified;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
isBuildPythonPackage = platforms;
|
|
|
|
|
schedulingPriority = int;
|
|
|
|
|
isFcitxEngine = bool;
|
|
|
|
|
isIbusEngine = bool;
|
|
|
|
|
isGutenprint = bool;
|
|
|
|
|
badPlatforms = platforms;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
checkMetaAttr = k: v:
|
|
|
|
|
if metaTypes?${k} then
|
2023-01-11 07:51:40 +00:00
|
|
|
|
if typeCheck metaTypes.${k} v then
|
2022-09-30 11:47:45 +00:00
|
|
|
|
null
|
|
|
|
|
else
|
2023-01-11 07:51:40 +00:00
|
|
|
|
"key 'meta.${k}' has invalid value; expected ${metaTypes.${k}.description}, got\n ${
|
|
|
|
|
lib.generators.toPretty { indent = " "; } v
|
|
|
|
|
}"
|
2022-09-30 11:47:45 +00:00
|
|
|
|
else
|
2023-01-11 07:51:40 +00:00
|
|
|
|
"key 'meta.${k}' is unrecognized; expected one of: \n [${lib.concatMapStringsSep ", " (x: "'${x}'") (lib.attrNames metaTypes)}]";
|
2023-02-16 17:41:37 +00:00
|
|
|
|
checkMeta = meta: lib.optionals config.checkMeta (lib.remove null (lib.mapAttrsToList checkMetaAttr meta));
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
|
|
checkOutputsToInstall = attrs: let
|
|
|
|
|
expectedOutputs = attrs.meta.outputsToInstall or [];
|
|
|
|
|
actualOutputs = attrs.outputs or [ "out" ];
|
|
|
|
|
missingOutputs = builtins.filter (output: ! builtins.elem output actualOutputs) expectedOutputs;
|
2022-09-30 11:47:45 +00:00
|
|
|
|
in if config.checkMeta
|
2020-04-24 23:36:52 +00:00
|
|
|
|
then builtins.length missingOutputs > 0
|
|
|
|
|
else false;
|
|
|
|
|
|
|
|
|
|
# Check if a derivation is valid, that is whether it passes checks for
|
|
|
|
|
# e.g brokenness or license.
|
|
|
|
|
#
|
2023-01-11 07:51:40 +00:00
|
|
|
|
# Return { valid: "yes", "warn" or "no" } and additionally
|
2020-04-24 23:36:52 +00:00
|
|
|
|
# { reason: String; errormsg: String } if it is not valid, where
|
2021-02-24 18:30:23 +00:00
|
|
|
|
# reason is one of "unfree", "blocklisted", "broken", "insecure", ...
|
2023-01-11 07:51:40 +00:00
|
|
|
|
# !!! reason strings are hardcoded into OfBorg, make sure to keep them in sync
|
2020-11-30 08:33:03 +00:00
|
|
|
|
# Along with a boolean flag for each reason
|
2020-04-24 23:36:52 +00:00
|
|
|
|
checkValidity = attrs:
|
2023-01-11 07:51:40 +00:00
|
|
|
|
# Check meta attribute types first, to make sure it is always called even when there are other issues
|
|
|
|
|
# Note that this is not a full type check and functions below still need to by careful about their inputs!
|
|
|
|
|
let res = checkMeta (attrs.meta or {}); in if res != [] then
|
|
|
|
|
{ valid = "no"; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n - " + x) res}\n";
|
|
|
|
|
unfree = false; nonSource = false; broken = false; unsupported = false; insecure = false;
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-11-30 08:33:03 +00:00
|
|
|
|
unfree = hasUnfreeLicense attrs;
|
2022-06-16 17:23:12 +00:00
|
|
|
|
nonSource = hasNonSourceProvenance attrs;
|
2020-11-30 08:33:03 +00:00
|
|
|
|
broken = isMarkedBroken attrs;
|
|
|
|
|
unsupported = hasUnsupportedPlatform attrs;
|
|
|
|
|
insecure = isMarkedInsecure attrs;
|
2023-01-11 07:51:40 +00:00
|
|
|
|
} // (
|
2022-09-30 11:47:45 +00:00
|
|
|
|
# --- Put checks that cannot be ignored here ---
|
2023-01-11 07:51:40 +00:00
|
|
|
|
if checkOutputsToInstall attrs then
|
2022-09-30 11:47:45 +00:00
|
|
|
|
{ valid = "no"; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
|
|
|
|
|
|
|
|
|
|
# --- Put checks that can be ignored here ---
|
|
|
|
|
else if hasDeniedUnfreeLicense attrs && !(hasAllowlistedLicense attrs) then
|
2022-04-27 09:35:20 +00:00
|
|
|
|
{ valid = "no"; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
|
2021-02-24 18:30:23 +00:00
|
|
|
|
else if hasBlocklistedLicense attrs then
|
2022-04-27 09:35:20 +00:00
|
|
|
|
{ valid = "no"; reason = "blocklisted"; errormsg = "has a blocklisted license (‘${showLicense attrs.meta.license}’)"; }
|
2022-06-16 17:23:12 +00:00
|
|
|
|
else if hasDeniedNonSourceProvenance attrs then
|
|
|
|
|
{ valid = "no"; reason = "non-source"; errormsg = "contains elements not built from source (‘${showSourceType attrs.meta.sourceProvenance}’)"; }
|
2020-04-24 23:36:52 +00:00
|
|
|
|
else if !allowBroken && attrs.meta.broken or false then
|
2022-04-27 09:35:20 +00:00
|
|
|
|
{ valid = "no"; reason = "broken"; errormsg = "is marked as broken"; }
|
2020-11-30 08:33:03 +00:00
|
|
|
|
else if !allowUnsupportedSystem && hasUnsupportedPlatform attrs then
|
2023-03-27 19:17:25 +00:00
|
|
|
|
let toPretty = lib.generators.toPretty {
|
|
|
|
|
allowPrettyValues = true;
|
|
|
|
|
indent = " ";
|
|
|
|
|
};
|
|
|
|
|
in { valid = "no"; reason = "unsupported";
|
|
|
|
|
errormsg = ''
|
|
|
|
|
is not available on the requested hostPlatform:
|
|
|
|
|
hostPlatform.config = "${hostPlatform.config}"
|
|
|
|
|
package.meta.platforms = ${toPretty (attrs.meta.platforms or [])}
|
|
|
|
|
package.meta.badPlatforms = ${toPretty (attrs.meta.badPlatforms or [])}
|
|
|
|
|
'';
|
|
|
|
|
}
|
2020-04-24 23:36:52 +00:00
|
|
|
|
else if !(hasAllowedInsecure attrs) then
|
2022-04-27 09:35:20 +00:00
|
|
|
|
{ valid = "no"; reason = "insecure"; errormsg = "is marked as insecure"; }
|
2022-09-30 11:47:45 +00:00
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
# --- warnings ---
|
|
|
|
|
# Please also update the type in /pkgs/top-level/config.nix alongside this.
|
|
|
|
|
else if hasNoMaintainers attrs then
|
|
|
|
|
{ valid = "warn"; reason = "maintainerless"; errormsg = "has no maintainers"; }
|
|
|
|
|
# -----
|
|
|
|
|
else { valid = "yes"; });
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
2023-05-24 13:37:59 +00:00
|
|
|
|
|
|
|
|
|
# The meta attribute is passed in the resulting attribute set,
|
|
|
|
|
# but it's not part of the actual derivation, i.e., it's not
|
|
|
|
|
# passed to the builder and is not a dependency. But since we
|
|
|
|
|
# include it in the result, it *is* available to nix-env for queries.
|
|
|
|
|
# Example:
|
|
|
|
|
# meta = checkMeta.commonMeta { inherit validity attrs pos references; };
|
|
|
|
|
# validity = checkMeta.assertValidity { inherit meta attrs; };
|
|
|
|
|
commonMeta = { validity, attrs, pos ? null, references ? [ ] }:
|
|
|
|
|
let
|
|
|
|
|
outputs = attrs.outputs or [ "out" ];
|
|
|
|
|
in
|
|
|
|
|
{
|
|
|
|
|
# `name` derivation attribute includes cross-compilation cruft,
|
|
|
|
|
# is under assert, and is sanitized.
|
|
|
|
|
# Let's have a clean always accessible version here.
|
|
|
|
|
name = attrs.name or "${attrs.pname}-${attrs.version}";
|
|
|
|
|
|
|
|
|
|
# If the packager hasn't specified `outputsToInstall`, choose a default,
|
|
|
|
|
# which is the name of `p.bin or p.out or p` along with `p.man` when
|
|
|
|
|
# present.
|
|
|
|
|
#
|
|
|
|
|
# If the packager has specified it, it will be overridden below in
|
|
|
|
|
# `// meta`.
|
|
|
|
|
#
|
|
|
|
|
# Note: This default probably shouldn't be globally configurable.
|
|
|
|
|
# Services and users should specify outputs explicitly,
|
|
|
|
|
# unless they are comfortable with this default.
|
|
|
|
|
outputsToInstall =
|
|
|
|
|
let
|
|
|
|
|
hasOutput = out: builtins.elem out outputs;
|
|
|
|
|
in
|
|
|
|
|
[ (lib.findFirst hasOutput null ([ "bin" "out" ] ++ outputs)) ]
|
|
|
|
|
++ lib.optional (hasOutput "man") "man";
|
|
|
|
|
}
|
|
|
|
|
// attrs.meta or { }
|
|
|
|
|
# Fill `meta.position` to identify the source location of the package.
|
|
|
|
|
// lib.optionalAttrs (pos != null) {
|
|
|
|
|
position = pos.file + ":" + toString pos.line;
|
|
|
|
|
} // {
|
|
|
|
|
# Expose the result of the checks for everyone to see.
|
|
|
|
|
inherit (validity) unfree broken unsupported insecure;
|
|
|
|
|
|
|
|
|
|
available = validity.valid != "no"
|
|
|
|
|
&& (if config.checkMetaRecursively or false
|
|
|
|
|
then lib.all (d: d.meta.available or true) references
|
|
|
|
|
else true);
|
|
|
|
|
};
|
|
|
|
|
|
2020-04-24 23:36:52 +00:00
|
|
|
|
assertValidity = { meta, attrs }: let
|
|
|
|
|
validity = checkValidity attrs;
|
|
|
|
|
in validity // {
|
2022-04-27 09:35:20 +00:00
|
|
|
|
# Throw an error if trying to evaluate a non-valid derivation
|
|
|
|
|
# or, alternatively, just output a warning message.
|
|
|
|
|
handled =
|
|
|
|
|
{
|
|
|
|
|
no = handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg; };
|
|
|
|
|
warn = handleEvalWarning { inherit meta attrs; } { inherit (validity) reason errormsg; };
|
|
|
|
|
yes = true;
|
|
|
|
|
}.${validity.valid};
|
2023-05-24 13:37:59 +00:00
|
|
|
|
|
2020-04-24 23:36:52 +00:00
|
|
|
|
};
|
|
|
|
|
|
2023-05-24 13:37:59 +00:00
|
|
|
|
in { inherit assertValidity commonMeta; }
|