Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions pkgs/stdenv/generic/check-meta.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ 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;
# Allow the user to opt-into additional warnings, e.g.
# import <nixpkgs> { config = { showDerivationWarnings = [ "maintainerless" ]; }; }
showWarnings = config.showDerivationWarnings;

getName = attrs: attrs.name or ("${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}");

# See discussion at https://github.com/NixOS/nixpkgs/pull/25304#issuecomment-298385426
Expand Down Expand Up @@ -46,6 +50,9 @@ let
hasLicense attrs &&
isUnfree (lib.lists.toList attrs.meta.license);

hasNoMaintainers = attrs:
attrs ? meta.maintainers && (lib.length attrs.meta.maintainers) == 0;

isMarkedBroken = attrs: attrs.meta.broken or false;

hasUnsupportedPlatform = attrs:
Expand Down Expand Up @@ -91,6 +98,7 @@ let
insecure = remediate_insecure;
broken-outputs = remediateOutputsToInstall;
unknown-meta = x: "";
maintainerless = x: "";
};
remediation_env_var = allow_attr: {
Unfree = "NIXPKGS_ALLOW_UNFREE";
Expand Down Expand Up @@ -199,6 +207,14 @@ let
else throw;
in handler msg;

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."
+ (if remediationMsg != "" then "\n${remediationMsg}" else "");
isEnabled = lib.findFirst (x: x == reason) null showWarnings;
in if isEnabled != null then builtins.trace msg true else true;

metaTypes = with lib.types; rec {
# These keys are documented
Expand Down Expand Up @@ -277,28 +293,37 @@ let
insecure = isMarkedInsecure attrs;
}
// (if hasDeniedUnfreeLicense attrs && !(hasAllowlistedLicense attrs) then
{ valid = false; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
{ valid = "no"; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; }
else if hasBlocklistedLicense attrs then
{ valid = false; reason = "blocklisted"; errormsg = "has a blocklisted license (‘${showLicense attrs.meta.license}’)"; }
{ valid = "no"; reason = "blocklisted"; errormsg = "has a blocklisted license (‘${showLicense attrs.meta.license}’)"; }
else if !allowBroken && attrs.meta.broken or false then
{ valid = false; reason = "broken"; errormsg = "is marked as broken"; }
{ valid = "no"; reason = "broken"; errormsg = "is marked as broken"; }
else if !allowUnsupportedSystem && hasUnsupportedPlatform attrs then
{ valid = false; reason = "unsupported"; errormsg = "is not supported on ‘${hostPlatform.system}’"; }
{ valid = "no"; reason = "unsupported"; errormsg = "is not supported on ‘${hostPlatform.system}’"; }
else if !(hasAllowedInsecure attrs) then
{ valid = false; reason = "insecure"; errormsg = "is marked as insecure"; }
{ valid = "no"; reason = "insecure"; errormsg = "is marked as insecure"; }
else if checkOutputsToInstall attrs then
{ valid = false; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
{ valid = "no"; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; }
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}"; }
else { valid = true; });
{ valid = "no"; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${lib.concatMapStrings (x: "\n\t - " + x) res}"; }
# --- 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"; });

assertValidity = { meta, attrs }: let
validity = checkValidity attrs;
in validity // {
# Throw an error if trying to evaluate an non-valid derivation
handled = if !validity.valid
then handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg; }
else true;
# 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};
};

in assertValidity
2 changes: 1 addition & 1 deletion pkgs/stdenv/generic/make-derivation.nix
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ else let
} // {
# Expose the result of the checks for everyone to see.
inherit (validity) unfree broken unsupported insecure;
available = validity.valid
available = validity.valid != "no"
&& (if config.checkMetaRecursively or false
then lib.all (d: d.meta.available or true) references
else true);
Expand Down
15 changes: 15 additions & 0 deletions pkgs/top-level/config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,21 @@ let
'';
};

showDerivationWarnings = mkOption {
type = types.listOf (types.enum [ "maintainerless" ]);
default = [];
description = ''
Which warnings to display for potentially dangerous
or deprecated values passed into `stdenv.mkDerivation`.

A list of warnings can be found in
<link xlink:href="https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/check-meta.nix">/pkgs/stdenv/generic/check-meta.nix</link>.

This is not a stable interface; warnings may be added, changed
or removed without prior notice.
'';
};

};

in {
Expand Down