meta: expose availability flags in derivation metadata
Currently it's not possible to determine the reason why a package is unavailable without evaluating nixpkgs multiple times with different settings. eg. nix-repl> :p android-studio.meta { available = false; broken = false; unfree = true; unsupported = true; ... } The following snippet is an example that uses this information to query the availability information of all packages in nixpkgs, giving an overview of all the packages currently marked as broken, etc. { pkgs }: with import <nixpkgs/lib>; let mapPkgs = let mapPkgs' = path: f: mapAttrs (n: v: let result = builtins.tryEval (v ? meta); in if !result.success then {} else if isDerivation v then f (path ++ [n]) v else if isAttrs v && v.recurseForDerivations or false then mapPkgs' (path ++ [n]) f v else {} ); in mapPkgs' []; getMeta = path: drv: if drv.meta ? available then let meta = { pkg = concatStringsSep "." path; inherit (drv.meta) broken unfree unsupported insecure; }; in builtins.trace meta.pkg meta else {}; metaToList = attrs: flatten (map (v: if v ? pkg then v else metaToList v) (attrValues attrs)); in metaToList (mapPkgs getMeta pkgs)
This commit is contained in:
parent
257aff8010
commit
950ac2bc8f
|
@ -49,6 +49,18 @@ let
|
||||||
|
|
||||||
isUnfree = licenses: lib.lists.any (l: !l.free or true) licenses;
|
isUnfree = licenses: lib.lists.any (l: !l.free or true) licenses;
|
||||||
|
|
||||||
|
hasUnfreeLicense = attrs:
|
||||||
|
hasLicense attrs &&
|
||||||
|
isUnfree (lib.lists.toList attrs.meta.license);
|
||||||
|
|
||||||
|
isMarkedBroken = attrs: attrs.meta.broken or false;
|
||||||
|
|
||||||
|
hasUnsupportedPlatform = attrs:
|
||||||
|
(!lib.lists.elem hostPlatform.system (attrs.meta.platforms or lib.platforms.all) ||
|
||||||
|
lib.lists.elem hostPlatform.system (attrs.meta.badPlatforms or []));
|
||||||
|
|
||||||
|
isMarkedInsecure = attrs: (attrs.meta.knownVulnerabilities or []) != [];
|
||||||
|
|
||||||
# Alow granular checks to allow only some unfree packages
|
# Alow granular checks to allow only some unfree packages
|
||||||
# Example:
|
# Example:
|
||||||
# {pkgs, ...}:
|
# {pkgs, ...}:
|
||||||
|
@ -62,16 +74,15 @@ let
|
||||||
# package has an unfree license and is not explicitely allowed by the
|
# package has an unfree license and is not explicitely allowed by the
|
||||||
# `allowUnfreePredicate` function.
|
# `allowUnfreePredicate` function.
|
||||||
hasDeniedUnfreeLicense = attrs:
|
hasDeniedUnfreeLicense = attrs:
|
||||||
|
hasUnfreeLicense attrs &&
|
||||||
!allowUnfree &&
|
!allowUnfree &&
|
||||||
hasLicense attrs &&
|
|
||||||
isUnfree (lib.lists.toList attrs.meta.license) &&
|
|
||||||
!allowUnfreePredicate attrs;
|
!allowUnfreePredicate attrs;
|
||||||
|
|
||||||
allowInsecureDefaultPredicate = x: builtins.elem (getName x) (config.permittedInsecurePackages or []);
|
allowInsecureDefaultPredicate = x: builtins.elem (getName x) (config.permittedInsecurePackages or []);
|
||||||
allowInsecurePredicate = x: (config.allowInsecurePredicate or allowInsecureDefaultPredicate) x;
|
allowInsecurePredicate = x: (config.allowInsecurePredicate or allowInsecureDefaultPredicate) x;
|
||||||
|
|
||||||
hasAllowedInsecure = attrs:
|
hasAllowedInsecure = attrs:
|
||||||
(attrs.meta.knownVulnerabilities or []) == [] ||
|
!(isMarkedInsecure attrs) ||
|
||||||
allowInsecurePredicate attrs ||
|
allowInsecurePredicate attrs ||
|
||||||
builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
|
builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
|
||||||
|
|
||||||
|
@ -173,6 +184,9 @@ let
|
||||||
platforms = listOf str;
|
platforms = listOf str;
|
||||||
hydraPlatforms = listOf str;
|
hydraPlatforms = listOf str;
|
||||||
broken = bool;
|
broken = bool;
|
||||||
|
unfree = bool;
|
||||||
|
unsupported = bool;
|
||||||
|
insecure = bool;
|
||||||
# TODO: refactor once something like Profpatsch's types-simple will land
|
# 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
|
# This is currently dead code due to https://github.com/NixOS/nix/issues/2532
|
||||||
tests = attrsOf (mkOptionType {
|
tests = attrsOf (mkOptionType {
|
||||||
|
@ -224,17 +238,22 @@ let
|
||||||
#
|
#
|
||||||
# Return { valid: Bool } and additionally
|
# Return { valid: Bool } and additionally
|
||||||
# { reason: String; errormsg: String } if it is not valid, where
|
# { reason: String; errormsg: String } if it is not valid, where
|
||||||
# reason is one of "unfree", "blacklisted" or "broken".
|
# reason is one of "unfree", "blacklisted", "broken", "insecure", ...
|
||||||
|
# Along with a boolean flag for each reason
|
||||||
checkValidity = attrs:
|
checkValidity = attrs:
|
||||||
if hasDeniedUnfreeLicense attrs && !(hasWhitelistedLicense attrs) then
|
{
|
||||||
|
unfree = hasUnfreeLicense attrs;
|
||||||
|
broken = isMarkedBroken attrs;
|
||||||
|
unsupported = hasUnsupportedPlatform attrs;
|
||||||
|
insecure = isMarkedInsecure attrs;
|
||||||
|
}
|
||||||
|
// (if hasDeniedUnfreeLicense attrs && !(hasWhitelistedLicense attrs) then
|
||||||
{ valid = false; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
|
{ valid = false; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
|
||||||
else if hasBlacklistedLicense attrs then
|
else if hasBlacklistedLicense attrs then
|
||||||
{ valid = false; reason = "blacklisted"; errormsg = "has a blacklisted license (‘${showLicense attrs.meta.license}’)"; }
|
{ valid = false; reason = "blacklisted"; errormsg = "has a blacklisted license (‘${showLicense attrs.meta.license}’)"; }
|
||||||
else if !allowBroken && attrs.meta.broken or false then
|
else if !allowBroken && attrs.meta.broken or false then
|
||||||
{ valid = false; reason = "broken"; errormsg = "is marked as broken"; }
|
{ valid = false; reason = "broken"; errormsg = "is marked as broken"; }
|
||||||
else if !allowUnsupportedSystem &&
|
else if !allowUnsupportedSystem && hasUnsupportedPlatform attrs then
|
||||||
(!lib.lists.elem hostPlatform.system (attrs.meta.platforms or lib.platforms.all) ||
|
|
||||||
lib.lists.elem hostPlatform.system (attrs.meta.badPlatforms or [])) then
|
|
||||||
{ valid = false; reason = "unsupported"; errormsg = "is not supported on ‘${hostPlatform.system}’"; }
|
{ valid = false; reason = "unsupported"; errormsg = "is not supported on ‘${hostPlatform.system}’"; }
|
||||||
else if !(hasAllowedInsecure attrs) then
|
else if !(hasAllowedInsecure attrs) then
|
||||||
{ valid = false; reason = "insecure"; errormsg = "is marked as insecure"; }
|
{ valid = false; reason = "insecure"; errormsg = "is marked as insecure"; }
|
||||||
|
@ -242,14 +261,14 @@ let
|
||||||
{ valid = false; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
|
{ valid = false; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
|
||||||
else let res = checkMeta (attrs.meta or {}); in if res != [] then
|
else let res = checkMeta (attrs.meta or {}); in if res != [] then
|
||||||
{ valid = false; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
|
{ valid = false; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
|
||||||
else { valid = true; };
|
else { valid = true; });
|
||||||
|
|
||||||
assertValidity = { meta, attrs }: let
|
assertValidity = { meta, attrs }: let
|
||||||
validity = checkValidity attrs;
|
validity = checkValidity attrs;
|
||||||
in validity // {
|
in validity // {
|
||||||
# Throw an error if trying to evaluate an non-valid derivation
|
# Throw an error if trying to evaluate an non-valid derivation
|
||||||
handled = if !validity.valid
|
handled = if !validity.valid
|
||||||
then handleEvalIssue { inherit meta attrs; } (removeAttrs validity ["valid"])
|
then handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg; }
|
||||||
else true;
|
else true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -302,8 +302,9 @@ in rec {
|
||||||
# Fill `meta.position` to identify the source location of the package.
|
# Fill `meta.position` to identify the source location of the package.
|
||||||
// lib.optionalAttrs (pos != null) {
|
// lib.optionalAttrs (pos != null) {
|
||||||
position = pos.file + ":" + toString pos.line;
|
position = pos.file + ":" + toString pos.line;
|
||||||
# Expose the result of the checks for everyone to see.
|
|
||||||
} // {
|
} // {
|
||||||
|
# Expose the result of the checks for everyone to see.
|
||||||
|
inherit (validity) unfree broken unsupported insecure;
|
||||||
available = validity.valid
|
available = validity.valid
|
||||||
&& (if config.checkMetaRecursively or false
|
&& (if config.checkMetaRecursively or false
|
||||||
then lib.all (d: d.meta.available or true) references
|
then lib.all (d: d.meta.available or true) references
|
||||||
|
|
Loading…
Reference in New Issue