mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-03-08 01:24:09 +01:00
stdenv.mkDerivation: Initial RFC 127 implementation
See https://github.com/NixOS/rfcs/blob/master/rfcs/0127-issues-warnings.md Co-Authored-By: piegames <git@piegames.de> Co-Authored-By: AkechiShiro <14914796+AkechiShiro@users.noreply.github.com>
This commit is contained in:
parent
8fe8f0eb36
commit
27dd434480
57 changed files with 1500 additions and 76 deletions
|
|
@ -58,8 +58,10 @@
|
|||
/pkgs/top-level/by-name-overlay.nix @infinisil @philiptaron
|
||||
/pkgs/stdenv @philiptaron @NixOS/stdenv
|
||||
/pkgs/stdenv/generic @Ericson2314 @NixOS/stdenv
|
||||
/pkgs/stdenv/generic/check-meta.nix @Ericson2314 @adisbladis @NixOS/stdenv
|
||||
/pkgs/stdenv/generic/meta-types.nix @adisbladis @NixOS/stdenv
|
||||
/pkgs/stdenv/generic/problems.nix @infinisil
|
||||
/pkgs/test/problems @infinisil
|
||||
/pkgs/stdenv/generic/check-meta.nix @infinisil @Ericson2314 @adisbladis @NixOS/stdenv
|
||||
/pkgs/stdenv/generic/meta-types.nix @infinisil @adisbladis @NixOS/stdenv
|
||||
/pkgs/stdenv/cross @Ericson2314 @NixOS/stdenv
|
||||
/pkgs/build-support @philiptaron
|
||||
/pkgs/build-support/cc-wrapper @Ericson2314
|
||||
|
|
|
|||
|
|
@ -629,6 +629,9 @@
|
|||
"chap-stdenv": [
|
||||
"index.html#chap-stdenv"
|
||||
],
|
||||
"sec-problems": [
|
||||
"index.html#sec-problems"
|
||||
],
|
||||
"sec-using-llvm": [
|
||||
"index.html#sec-using-llvm"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ By default, Nix will prevent installation if any of the following criteria are t
|
|||
|
||||
- The package has known security vulnerabilities but has not or can not be updated for some reason, and a list of issues has been entered into the package's `meta.knownVulnerabilities`.
|
||||
|
||||
- There are problems for packages which must be acknowledged, e.g. deprecation notices.
|
||||
|
||||
Each of these criteria can be altered in the Nixpkgs configuration.
|
||||
|
||||
:::{.note}
|
||||
|
|
@ -166,6 +168,57 @@ There are several ways to tweak how Nix handles a package which has been marked
|
|||
|
||||
Note that `permittedInsecurePackages` is only checked if `allowInsecurePredicate` is not specified.
|
||||
|
||||
## Packages with problems {#sec-problems}
|
||||
|
||||
A package may have several problems associated with it.
|
||||
These can be either manually declared in `meta.problems`, or automatically generated from its other `meta` attributes.
|
||||
Each problem has a name, a "kind", a message, and optionally a list of URLs.
|
||||
Not all kinds can be manually specified in `meta.problems`, and some kinds can exist only up to once per package.
|
||||
Currently, the following problem kinds are known (with more reserved to be added in the future):
|
||||
|
||||
- "removal": The package is planned to be removed some time in the future. Unique.
|
||||
- "deprecated": The package relies on software which has reached its end of life.
|
||||
- "maintainerless": Automatically generated for packages with `meta.maintainers == []`. Unique, not manually specifiable.
|
||||
|
||||
Each problem has a handler that deals with it, which can be one of "error", "warn" or "ignore".
|
||||
"error" will disallow evaluating a package, while "warn" will simply print a message to the log.
|
||||
|
||||
The handler for problems can be specified using `config.problems.handlers.${packageName}.${problemName} = "${handler}";`.
|
||||
|
||||
There is also the possibility to specify some generic matchers, which can set a handler for more than a specific problem of a specific package.
|
||||
This works through the `config.problems.matchers` option:
|
||||
|
||||
```nix
|
||||
{
|
||||
problems.matchers = [
|
||||
# Fail to build any packages which are about to be removed anyway
|
||||
{
|
||||
kind = "removal";
|
||||
handler = "error";
|
||||
}
|
||||
|
||||
# Get warnings when using packages with no declared maintainers
|
||||
{
|
||||
kind = "maintainerless";
|
||||
handler = "warn";
|
||||
}
|
||||
|
||||
# You deeply care about this package and want to absolutely know when it has any problems
|
||||
{
|
||||
package = "hello";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Matchers can match one or more of package name, problem name or problem kind.
|
||||
If multiple conditions are present, all must be met to match.
|
||||
If multiple matchers match a problem, then the highest severity handler will be chosen.
|
||||
The current default value contains `{ kind = "removal"; handler = "warn"; }`, meaning that people will be notified about package removals in advance.
|
||||
|
||||
Package names for both `problems.handlers` and `problems.matchers` are taken from `lib.getName`, which looks at the `pname` first and falls back to extracting the "pname" part from the `name` attribute.
|
||||
|
||||
## Modify packages via `packageOverrides` {#sec-modify-via-packageOverrides}
|
||||
|
||||
You can define a function called `packageOverrides` in your local `~/.config/nixpkgs/config.nix` to override Nix packages. It must be a function that takes pkgs as an argument and returns a modified set of packages.
|
||||
|
|
|
|||
|
|
@ -10,10 +10,8 @@
|
|||
let
|
||||
inherit (lib)
|
||||
all
|
||||
attrNames
|
||||
attrValues
|
||||
concatMapStrings
|
||||
concatMapStringsSep
|
||||
concatStrings
|
||||
filter
|
||||
findFirst
|
||||
|
|
@ -26,7 +24,8 @@ let
|
|||
optionalString
|
||||
isAttrs
|
||||
isString
|
||||
mapAttrs
|
||||
warn
|
||||
foldl'
|
||||
;
|
||||
|
||||
inherit (lib.lists)
|
||||
|
|
@ -49,15 +48,17 @@ let
|
|||
|
||||
inherit (builtins)
|
||||
getEnv
|
||||
trace
|
||||
;
|
||||
|
||||
inherit (import ./problems.nix { inherit lib; })
|
||||
problemsType
|
||||
genCheckProblems
|
||||
;
|
||||
checkProblems = genCheckProblems config;
|
||||
|
||||
# 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;
|
||||
|
||||
getNameWithVersion =
|
||||
attrs: attrs.name or "${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}";
|
||||
|
|
@ -118,21 +119,6 @@ let
|
|||
|
||||
hasUnfreeLicense = attrs: attrs ? meta.license && isUnfree attrs.meta.license;
|
||||
|
||||
hasNoMaintainers =
|
||||
# To get usable output, we want to avoid flagging "internal" derivations.
|
||||
# Because we do not have a way to reliably decide between internal or
|
||||
# external derivation, some heuristics are required to decide.
|
||||
#
|
||||
# If `outputHash` is defined, the derivation is a FOD, such as the output of a fetcher.
|
||||
# If `description` is not defined, the derivation is probably not a package.
|
||||
# Simply checking whether `meta` is defined is insufficient,
|
||||
# as some fetchers and trivial builders do define meta.
|
||||
attrs:
|
||||
(!attrs ? outputHash)
|
||||
&& (attrs ? meta.description)
|
||||
&& (attrs.meta.maintainers or [ ] == [ ])
|
||||
&& (attrs.meta.teams or [ ] == [ ]);
|
||||
|
||||
isMarkedBroken = attrs: attrs.meta.broken or false;
|
||||
|
||||
# Allow granular checks to allow only some broken packages
|
||||
|
|
@ -375,6 +361,8 @@ let
|
|||
unfree = bool;
|
||||
unsupported = bool;
|
||||
insecure = bool;
|
||||
# This is checked in more detail further down
|
||||
problems = problemsType;
|
||||
timeout = int;
|
||||
knownVulnerabilities = listOf str;
|
||||
badPlatforms = platforms;
|
||||
|
|
@ -497,18 +485,6 @@ let
|
|||
else
|
||||
null;
|
||||
|
||||
# Please also update the type in /pkgs/top-level/config.nix alongside this.
|
||||
checkWarnings =
|
||||
attrs:
|
||||
if hasNoMaintainers attrs then
|
||||
{
|
||||
reason = "maintainerless";
|
||||
msg = "has no maintainers or teams";
|
||||
remediation = "";
|
||||
}
|
||||
else
|
||||
null;
|
||||
|
||||
# Helper functions and declarations to handle identifiers, extracted to reduce allocations
|
||||
hasAllCPEParts =
|
||||
cpeParts:
|
||||
|
|
@ -669,52 +645,64 @@ let
|
|||
&& ((config.checkMetaRecursively or false) -> all (d: d.meta.available or true) references);
|
||||
};
|
||||
|
||||
validYes = {
|
||||
valid = "yes";
|
||||
handled = true;
|
||||
};
|
||||
handle =
|
||||
{
|
||||
attrs,
|
||||
meta,
|
||||
warnings ? [ ],
|
||||
error ? null,
|
||||
}:
|
||||
let
|
||||
withError =
|
||||
if isNull error then
|
||||
true
|
||||
else
|
||||
let
|
||||
msg =
|
||||
"Refusing to evaluate package '${getNameWithVersion attrs}' in ${pos_str meta} because it ${error.msg}"
|
||||
+ lib.optionalString (!inHydra && error.remediation != "") "\n${error.remediation}";
|
||||
in
|
||||
if config ? handleEvalIssue then config.handleEvalIssue error.reason msg else throw msg;
|
||||
|
||||
giveWarning =
|
||||
acc: warning:
|
||||
let
|
||||
msg =
|
||||
"Package '${getNameWithVersion attrs}' in ${pos_str meta} ${warning.msg}"
|
||||
+ lib.optionalString (!inHydra && warning.remediation != "") " ${warning.remediation}";
|
||||
in
|
||||
warn msg acc;
|
||||
in
|
||||
# Give all warnings first, then error if any
|
||||
builtins.seq (foldl' giveWarning null warnings) withError;
|
||||
|
||||
assertValidity =
|
||||
{ meta, attrs }:
|
||||
let
|
||||
invalid = checkValidity attrs;
|
||||
warning = checkWarnings attrs;
|
||||
problems = checkProblems attrs;
|
||||
in
|
||||
if isNull invalid then
|
||||
if isNull warning then
|
||||
validYes
|
||||
else
|
||||
let
|
||||
msg =
|
||||
if inHydra then
|
||||
"Warning while evaluating ${getNameWithVersion attrs}: «${warning.reason}»: ${warning.msg}"
|
||||
else
|
||||
"Package ${getNameWithVersion attrs} in ${pos_str meta} ${warning.msg}, continuing anyway."
|
||||
+ (optionalString (warning.remediation != "") "\n${warning.remediation}");
|
||||
|
||||
handled = if elem warning.reason showWarnings then trace msg true else true;
|
||||
in
|
||||
if isNull problems then
|
||||
{
|
||||
valid = "warn";
|
||||
handled = handled;
|
||||
valid = "yes";
|
||||
handled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = if isNull problems.error then "warn" else "no";
|
||||
handled = handle {
|
||||
inherit attrs meta;
|
||||
inherit (problems) error warnings;
|
||||
};
|
||||
}
|
||||
else
|
||||
let
|
||||
msg =
|
||||
if inHydra then
|
||||
"Failed to evaluate ${getNameWithVersion attrs}: «${invalid.reason}»: ${invalid.msg}"
|
||||
else
|
||||
''
|
||||
Package ‘${getNameWithVersion attrs}’ in ${pos_str meta} ${invalid.msg}, refusing to evaluate.
|
||||
|
||||
''
|
||||
+ invalid.remediation;
|
||||
|
||||
handled = if config ? handleEvalIssue then config.handleEvalIssue invalid.reason msg else throw msg;
|
||||
in
|
||||
{
|
||||
valid = "no";
|
||||
handled = handled;
|
||||
handled = handle {
|
||||
inherit attrs meta;
|
||||
error = invalid;
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
# TODO: add a method to the module system types
|
||||
# see https://github.com/NixOS/nixpkgs/pull/273935#issuecomment-1854173100
|
||||
let
|
||||
inherit (builtins)
|
||||
inherit (lib)
|
||||
isString
|
||||
isInt
|
||||
isAttrs
|
||||
|
|
@ -167,7 +167,7 @@ lib.fix (self: {
|
|||
concatMap (
|
||||
k:
|
||||
if fieldVerifiers ? ${k} then
|
||||
lib.optionals (fieldVerifiers.${k} v.${k}) (self.errors fields.${k} (ctx + ".${k}") v.${k})
|
||||
lib.optionals (!fieldVerifiers.${k} v.${k}) (self.errors fields.${k} "${ctx}.${k}" v.${k})
|
||||
else
|
||||
[
|
||||
"${ctx}: key '${k}' is unrecognized; expected one of: \n [${
|
||||
|
|
|
|||
515
pkgs/stdenv/generic/problems.nix
Normal file
515
pkgs/stdenv/generic/problems.nix
Normal file
|
|
@ -0,0 +1,515 @@
|
|||
/*
|
||||
This file implements everything around meta.problems, including:
|
||||
- automaticProblems: Which problems get added automatically based on some condition
|
||||
- configOptions: Module system options for config.problems
|
||||
- problemsType: The check for meta.problems
|
||||
- genHandlerSwitch: The logic to determine the handler for a specific problem based on config.problems
|
||||
- genCheckProblems: The logic to determine which problems need to be handled and how the messages should look like
|
||||
|
||||
There are tests to cover pretty much this entire file, so please run them when making changes ;)
|
||||
|
||||
nix-build -A tests.problems
|
||||
*/
|
||||
|
||||
{ lib }:
|
||||
|
||||
rec {
|
||||
|
||||
inherit (lib.strings)
|
||||
escapeNixIdentifier
|
||||
;
|
||||
|
||||
inherit (lib)
|
||||
any
|
||||
listToAttrs
|
||||
concatStringsSep
|
||||
optionalString
|
||||
getName
|
||||
optionalAttrs
|
||||
pipe
|
||||
isString
|
||||
filterAttrs
|
||||
mapAttrs
|
||||
partition
|
||||
elemAt
|
||||
max
|
||||
foldl'
|
||||
elem
|
||||
filter
|
||||
concatMapStringsSep
|
||||
optional
|
||||
optionals
|
||||
concatLists
|
||||
all
|
||||
attrNames
|
||||
attrValues
|
||||
length
|
||||
mapAttrsToList
|
||||
groupBy
|
||||
subtractLists
|
||||
genAttrs
|
||||
;
|
||||
|
||||
handlers = rec {
|
||||
# Ordered from less to more
|
||||
levels = [
|
||||
"ignore"
|
||||
"warn"
|
||||
"error"
|
||||
];
|
||||
|
||||
lessThan =
|
||||
a: b:
|
||||
if a == "error" then
|
||||
false
|
||||
else if a == "warn" then
|
||||
b == "error"
|
||||
else
|
||||
b != "ignore";
|
||||
|
||||
max = a: b: if lessThan a b then b else a;
|
||||
};
|
||||
|
||||
# TODO: Combine this and automaticProblems into a `{ removal = { manual = true; ... }; ... }` structure for less error-prone changes
|
||||
kinds = rec {
|
||||
# Automatic and manual problem kinds
|
||||
known = map (problem: problem.kindName) automaticProblems ++ manual;
|
||||
# Problem kinds that are currently allowed to be specified in `meta.problems`
|
||||
manual = [
|
||||
"removal"
|
||||
"deprecated"
|
||||
];
|
||||
# Problem kinds that are currently only allowed to be specified once
|
||||
unique = [
|
||||
"removal"
|
||||
];
|
||||
|
||||
# Same thing but a set with null values (comes in handy at times)
|
||||
manual' = genAttrs manual (k: null);
|
||||
unique' = genAttrs unique (k: null);
|
||||
};
|
||||
|
||||
automaticProblems = [
|
||||
{
|
||||
kindName = "maintainerless";
|
||||
condition =
|
||||
# To get usable output, we want to avoid flagging "internal" derivations.
|
||||
# Because we do not have a way to reliably decide between internal or
|
||||
# external derivation, some heuristics are required to decide.
|
||||
#
|
||||
# If `outputHash` is defined, the derivation is a FOD, such as the output of a fetcher.
|
||||
# If `description` is not defined, the derivation is probably not a package.
|
||||
# Simply checking whether `meta` is defined is insufficient,
|
||||
# as some fetchers and trivial builders do define meta.
|
||||
attrs:
|
||||
# Order of checks optimised for short-circuiting the common case of having maintainers
|
||||
(attrs.meta.maintainers or [ ] == [ ])
|
||||
&& (attrs.meta.teams or [ ] == [ ])
|
||||
&& (!attrs ? outputHash)
|
||||
&& (attrs ? meta.description);
|
||||
value.message = "This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute.";
|
||||
}
|
||||
];
|
||||
|
||||
genAutomaticProblems =
|
||||
attrs:
|
||||
listToAttrs (
|
||||
map (problem: lib.nameValuePair problem.kindName problem.value) (
|
||||
filter (problem: problem.condition attrs) automaticProblems
|
||||
)
|
||||
);
|
||||
|
||||
# A module system type for Nixpkgs config
|
||||
configOptions =
|
||||
let
|
||||
types = lib.types;
|
||||
handlerType = types.enum handlers.levels;
|
||||
problemKindType = types.enum kinds.known;
|
||||
in
|
||||
{
|
||||
handlers = lib.mkOption {
|
||||
type = with types; attrsOf (attrsOf handlerType);
|
||||
default = { };
|
||||
description = ''
|
||||
Specify how to handle packages with problems.
|
||||
Each key has the format `packageName.problemName`, each value is one of "error", "warn" or "ignore".
|
||||
|
||||
This option takes precedence over anything in `problems.matchers`.
|
||||
|
||||
Package names are taken from `lib.getName`, which looks at the `pname` first and falls back to extracting the "pname" part from the `name` attribute.
|
||||
|
||||
See <link xlink:href="https://nixos.org/manual/nixpkgs/stable/#sec-ignore-problems">Installing packages with problems</link> in the NixOS manual.
|
||||
'';
|
||||
};
|
||||
|
||||
matchers = lib.mkOption {
|
||||
type = types.listOf (
|
||||
types.submodule (
|
||||
{ config, ... }:
|
||||
{
|
||||
options = {
|
||||
package = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "Match problems of packages with this name";
|
||||
default = null;
|
||||
};
|
||||
name = lib.mkOption {
|
||||
type = types.nullOr types.str;
|
||||
description = "Match problems with this problem name";
|
||||
default = null;
|
||||
};
|
||||
kind = lib.mkOption {
|
||||
type = types.nullOr problemKindType;
|
||||
description = "Match problems of this problem kind";
|
||||
default = null;
|
||||
};
|
||||
handler = lib.mkOption {
|
||||
type = handlerType;
|
||||
description = "Specify the handler for matched problems";
|
||||
};
|
||||
|
||||
# Temporary hack to get assertions in submodules, see global assertions below
|
||||
assertions = lib.mkOption {
|
||||
type = types.listOf types.anything;
|
||||
default = [ ];
|
||||
internal = true;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
assertions =
|
||||
# Using optional because otherwise message would be evaluated even when assertion is true
|
||||
(
|
||||
optional (config.package != null && config.name != null) {
|
||||
assertion = false;
|
||||
# TODO: Does it really matter if we let people specify this? Maybe not, so consider removing this assertion
|
||||
message = ''
|
||||
There is a problems.matchers with `package = "${config.package}"` and `name = "${config.name}". Use the following instead:
|
||||
problems.handlers.${escapeNixIdentifier config.package}.${escapeNixIdentifier config.name} = "${config.handler}";
|
||||
'';
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
default = [ ];
|
||||
description = ''
|
||||
A more powerful and less ergonomic version of `problems.handlers`.
|
||||
Each value is a matcher, that may match onto certain properties of a problem and specify a handler for them.
|
||||
|
||||
If multiple matchers match a problem, the handler with the highest severity (error > warn > ignore) will be used.
|
||||
Values in `problems.handlers` always take precedence over matchers.
|
||||
|
||||
Any matchers must not contain both a `package` and `name` field, for this should be handled by using `problems.handlers` instead.
|
||||
'';
|
||||
example = [
|
||||
{
|
||||
kind = "maintainerless";
|
||||
handler = "warn";
|
||||
}
|
||||
{
|
||||
package = "myPackageICareAbout";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
# The type for meta.problems
|
||||
problemsType =
|
||||
let
|
||||
types = import ./meta-types.nix { inherit lib; };
|
||||
inherit (types)
|
||||
str
|
||||
listOf
|
||||
attrsOf
|
||||
record
|
||||
enum
|
||||
;
|
||||
kindType = enum kinds.manual;
|
||||
subRecord = record {
|
||||
kind = kindType;
|
||||
message = str;
|
||||
urls = listOf str;
|
||||
};
|
||||
simpleType = attrsOf subRecord;
|
||||
in
|
||||
{
|
||||
name = "problems";
|
||||
verify =
|
||||
v:
|
||||
v == { }
|
||||
||
|
||||
simpleType.verify v
|
||||
&& all (problem: problem ? message) (attrValues v)
|
||||
&& (
|
||||
let
|
||||
kindGroups = groupBy (kind: kind) (mapAttrsToList (name: problem: problem.kind or name) v);
|
||||
in
|
||||
all (kind: kinds.manual' ? ${kind} && (kinds.unique' ? ${kind} -> length kindGroups.${kind} == 1)) (
|
||||
attrNames kindGroups
|
||||
)
|
||||
);
|
||||
errors =
|
||||
ctx: v:
|
||||
let
|
||||
kindGroups = groupBy (attrs: attrs.kind) (
|
||||
mapAttrsToList (name: problem: {
|
||||
inherit name;
|
||||
explicit = problem ? kind;
|
||||
kind = problem.kind or name;
|
||||
}) v
|
||||
);
|
||||
in
|
||||
if !simpleType.verify v then
|
||||
types.errors simpleType ctx v
|
||||
else
|
||||
concatLists (
|
||||
mapAttrsToList (name: p: optional (!p ? message) "${ctx}.${name}: `.message` not specified") v
|
||||
)
|
||||
++ concatLists (
|
||||
mapAttrsToList (
|
||||
kind: kindGroup:
|
||||
optionals (!kinds.manual' ? ${kind}) (
|
||||
map (
|
||||
el:
|
||||
"${ctx}.${el.name}: Problem kind ${kind}, inferred from the problem name, is invalid; expected ${kindType.name}. You can specify an explicit problem kind with `${ctx}.${el.name}.kind`"
|
||||
) (filter (el: !el.explicit) kindGroup)
|
||||
)
|
||||
++
|
||||
optional (kinds.unique' ? ${kind} && length kindGroup > 1)
|
||||
"${ctx}: Problem kind ${kind} should be unique, but is used for these problems: ${
|
||||
concatMapStringsSep ", " (el: el.name) kindGroup
|
||||
}"
|
||||
) kindGroups
|
||||
);
|
||||
};
|
||||
|
||||
/*
|
||||
Construct a structure as follows, with the invariant that a more specific path always has a stricter handler, forming a lattice.
|
||||
E.g. if `packageSpecific.foo.nameFallback.kindFallback == "warn"`, then `packageFallback.nameFallback.kindFallback` must be "ignore".
|
||||
|
||||
packageSpecific.<package> = {
|
||||
nameSpecific.<name> = {
|
||||
kindSpecific.<kind> = <ignore|warn|error>;
|
||||
kindFallback = <ignore|warn|error>;
|
||||
};
|
||||
nameFallback = {
|
||||
kindSpecific.<kind> = <ignore|warn|error>;
|
||||
kindFallback = <ignore|warn|error>;
|
||||
};
|
||||
};
|
||||
packageFallback = {
|
||||
nameSpecific.<name> = {
|
||||
kindSpecific.<kind> = <ignore|warn|error>;
|
||||
kindFallback = <ignore|warn|error>;
|
||||
};
|
||||
nameFallback = {
|
||||
kindSpecific.<kind> = <ignore|warn|error>;
|
||||
kindFallback = <ignore|warn|error>;
|
||||
};
|
||||
};
|
||||
|
||||
Returns both the structure itself for inspection and a function that can query it with very few allocations/lookups
|
||||
|
||||
This allows collapsing arbitrarily many problem handlers/matchers into a predictable structure that can be queried in a predictable and fast way
|
||||
*/
|
||||
genHandlerSwitch =
|
||||
config:
|
||||
let
|
||||
constraints =
|
||||
# matchers have low priority
|
||||
map (m: m // { priority = 0; }) config.problems.matchers
|
||||
# handlers have higher priority
|
||||
++ concatLists (
|
||||
mapAttrsToList (
|
||||
package: forPackage:
|
||||
mapAttrsToList (name: handler: {
|
||||
inherit package name handler;
|
||||
kind = null;
|
||||
priority = 1;
|
||||
}) forPackage
|
||||
) config.problems.handlers
|
||||
);
|
||||
|
||||
getHandler =
|
||||
list:
|
||||
(foldl'
|
||||
(acc: el: {
|
||||
priority = max acc.priority el.priority;
|
||||
handler =
|
||||
if acc.priority == el.priority then
|
||||
handlers.max acc.handler el.handler
|
||||
else if acc.priority > el.priority then
|
||||
acc.handler
|
||||
else
|
||||
el.handler;
|
||||
})
|
||||
{
|
||||
priority = 0;
|
||||
handler = "ignore";
|
||||
}
|
||||
list
|
||||
).handler;
|
||||
|
||||
identOrder = [
|
||||
"kind"
|
||||
"name"
|
||||
"package"
|
||||
];
|
||||
|
||||
doLevel =
|
||||
index:
|
||||
let
|
||||
ident = elemAt identOrder index;
|
||||
nextLevel = if index + 1 == length identOrder then getHandler else doLevel (index + 1);
|
||||
in
|
||||
list:
|
||||
let
|
||||
# Partition all matchers into ident-specific (.wrong) and -unspecific (.right) ones
|
||||
parted = partition (m: isNull m.${ident}) list;
|
||||
# We only use the unspecific ones to compute the fallback
|
||||
fallback = nextLevel parted.right;
|
||||
specific = pipe parted.wrong [
|
||||
(groupBy (m: m.${ident}))
|
||||
# For ident-specific handlers, the unspecific ones also apply
|
||||
(mapAttrs (package: handlers: nextLevel (handlers ++ parted.right)))
|
||||
# Memory optimisation: Don't need a specific handler if it would end up the same as the fallback
|
||||
(filterAttrs (name: res: res != fallback))
|
||||
];
|
||||
in
|
||||
# Optimisation in case it's always the same handler,
|
||||
# can propagate up for the entire switch to just be a string
|
||||
if specific == { } && isString fallback then
|
||||
fallback
|
||||
else
|
||||
{
|
||||
"${ident}Fallback" = fallback;
|
||||
"${ident}Specific" = specific;
|
||||
};
|
||||
switch = doLevel 0 constraints;
|
||||
in
|
||||
{
|
||||
inherit switch;
|
||||
handlerForProblem =
|
||||
if isString switch then
|
||||
pname: name: kind:
|
||||
switch
|
||||
else
|
||||
pname: name: kind:
|
||||
let
|
||||
switch' = switch.kindSpecific.${kind} or switch.kindFallback;
|
||||
in
|
||||
if isString switch' then
|
||||
switch'
|
||||
else
|
||||
let
|
||||
switch'' = switch'.nameSpecific.${name} or switch'.nameFallback;
|
||||
in
|
||||
if isString switch'' then
|
||||
switch''
|
||||
else
|
||||
switch''.packageSpecific.${pname} or switch''.packageFallback;
|
||||
};
|
||||
|
||||
genCheckProblems =
|
||||
config:
|
||||
let
|
||||
# This is here so that it gets cached for a (checkProblems config) thunk
|
||||
inherit (genHandlerSwitch config)
|
||||
handlerForProblem
|
||||
;
|
||||
in
|
||||
attrs:
|
||||
let
|
||||
pname = getName attrs;
|
||||
manualProblems = attrs.meta.problems or { };
|
||||
in
|
||||
if
|
||||
# Fast path for when there's no problem that needs to be handled
|
||||
# No automatic problems that needs handling
|
||||
all (
|
||||
problem:
|
||||
problem.condition attrs -> handlerForProblem pname problem.kindName problem.kindName == "ignore"
|
||||
) automaticProblems
|
||||
&& (
|
||||
# No manual problems
|
||||
manualProblems == { }
|
||||
# Or all manual problems are ignored
|
||||
|| all (name: handlerForProblem pname name (manualProblems.${name}.kind or name) == "ignore") (
|
||||
attrNames manualProblems
|
||||
)
|
||||
)
|
||||
then
|
||||
null
|
||||
else
|
||||
# Slow path, only here we actually figure out which problems we need to handle
|
||||
let
|
||||
problems = attrs.meta.problems or { } // genAutomaticProblems attrs;
|
||||
problemsToHandle = filter (v: v.handler != "ignore") (
|
||||
mapAttrsToList (name: problem: rec {
|
||||
inherit name;
|
||||
# Kind falls back to the name
|
||||
kind = problem.kind or name;
|
||||
handler = handlerForProblem pname name kind;
|
||||
inherit problem;
|
||||
}) problems
|
||||
);
|
||||
in
|
||||
processProblems pname problemsToHandle;
|
||||
|
||||
processProblems =
|
||||
pname: problemsToHandle:
|
||||
let
|
||||
grouped = groupBy (v: v.handler) problemsToHandle;
|
||||
|
||||
warnProblems = grouped.warn or [ ];
|
||||
errorProblems = grouped.error or [ ];
|
||||
|
||||
# assert annotatedProblems != [ ];
|
||||
fullMessage =
|
||||
v:
|
||||
"${v.name}${optionalString (v.kind != v.name) " (kind \"${v.kind}\")"}: "
|
||||
+ "${v.problem.message}${
|
||||
optionalString (v.problem.urls or [ ] != [ ]) " (${concatStringsSep ", " v.problem.urls})"
|
||||
}";
|
||||
|
||||
warnings = map (x: {
|
||||
reason = "problem";
|
||||
msg = "has the following problem: ${fullMessage x}";
|
||||
remediation = "See https://nixos.org/manual/nixpkgs/unstable#sec-problems"; # TODO: Add remediation, maybe just link to docs to keep it small
|
||||
}) warnProblems;
|
||||
|
||||
error =
|
||||
if errorProblems == [ ] then
|
||||
null
|
||||
else
|
||||
{
|
||||
msg = ''
|
||||
has problems:
|
||||
${concatMapStringsSep "\n" (x: "- ${fullMessage x}") errorProblems}
|
||||
'';
|
||||
## TODO: Add mention of problem.matchers, or maybe better link to docs of that
|
||||
remediation = ''
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
${concatMapStringsSep "\n " (
|
||||
problem:
|
||||
''${escapeNixIdentifier pname}.${escapeNixIdentifier problem.name} = "warn"; # or "ignore"''
|
||||
) errorProblems}
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit error warnings;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -187,6 +187,11 @@ in
|
|||
|
||||
texlive = recurseIntoAttrs (callPackage ./texlive { });
|
||||
|
||||
# TODO: Temporarily disabled recursion so we can see the performance comparison in the PR,
|
||||
# which only runs if there's exactly the same packages before and after, and this would add packages
|
||||
#problems = recurseIntoAttrs (callPackage ./problems { });
|
||||
problems = callPackage ./problems { };
|
||||
|
||||
cuda = callPackage ./cuda { };
|
||||
|
||||
trivial-builders = callPackage ../build-support/trivial-builders/test/default.nix { };
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."deprecated" = "error";
|
||||
"a"."removal" = "error";
|
||||
"a"."maintainerless" = "error";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.problems = {
|
||||
deprecated.message = "Package is deprecated and replaced by b.";
|
||||
removal.message = "Package will be removed.";
|
||||
};
|
||||
meta.maintainers = [ ];
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:18 because it has problems:
|
||||
- deprecated: Package is deprecated and replaced by b.
|
||||
- maintainerless: This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute.
|
||||
- removal: Package will be removed.
|
||||
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
a.deprecated = "warn"; # or "ignore"
|
||||
a.maintainerless = "warn"; # or "ignore"
|
||||
a.removal = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."deprecated" = "error";
|
||||
"a"."removal" = "error";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems = {
|
||||
deprecated.message = "Package is deprecated and replaced by b";
|
||||
removal.message = "Package will be removed";
|
||||
};
|
||||
meta.maintainers = [ "hello" ];
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:16 because it has problems:
|
||||
- deprecated: Package is deprecated and replaced by b
|
||||
- removal: Package will be removed
|
||||
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
a.deprecated = "warn"; # or "ignore"
|
||||
a.removal = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
20
pkgs/test/problems/cases/deprecated-error/default.nix
Normal file
20
pkgs/test/problems/cases/deprecated-error/default.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."deprecated" = "error";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems.deprecated = {
|
||||
message = "Package is deprecated and replaced by b";
|
||||
};
|
||||
meta.maintainers = [ "hello" ];
|
||||
}
|
||||
16
pkgs/test/problems/cases/deprecated-error/expected-stderr
Normal file
16
pkgs/test/problems/cases/deprecated-error/expected-stderr
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:15 because it has problems:
|
||||
- deprecated: Package is deprecated and replaced by b
|
||||
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
a.deprecated = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
18
pkgs/test/problems/cases/deprecated-ignore/default.nix
Normal file
18
pkgs/test/problems/cases/deprecated-ignore/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."deprecated" = "ignore";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems.deprecated.message = "Package is deprecated and is replaced by b.";
|
||||
meta.maintainers = [ "hello" ];
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
18
pkgs/test/problems/cases/deprecated-warn/default.nix
Normal file
18
pkgs/test/problems/cases/deprecated-warn/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."deprecated" = "warn";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems.deprecated.message = "Package a is deprecated and superseeded by b.";
|
||||
meta.maintainers = [ "hello" ];
|
||||
}
|
||||
2
pkgs/test/problems/cases/deprecated-warn/expected-stderr
Normal file
2
pkgs/test/problems/cases/deprecated-warn/expected-stderr
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:15 has the following problem: deprecated: Package a is deprecated and superseeded by b. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
15
pkgs/test/problems/cases/invalid-kind-error/default.nix
Normal file
15
pkgs/test/problems/cases/invalid-kind-error/default.nix
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config.checkMeta = true;
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems = {
|
||||
invalid.message = "No maintainers";
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:11 because it has an invalid meta attrset:
|
||||
- a.meta.problems.invalid: Problem kind invalid, inferred from the problem name, is invalid; expected enum<removal,deprecated>. You can specify an explicit problem kind with `a.meta.problems.invalid.kind`
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."maintainerless" = "warn";
|
||||
"a"."deprecated" = "warn";
|
||||
"a"."removal" = "warn";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.maintainers = [ ];
|
||||
meta.problems = {
|
||||
removal.message = "Package to be removed.";
|
||||
deprecated.message = "Package will be deprecated.";
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:18 has the following problem: deprecated: Package will be deprecated. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:18 has the following problem: maintainerless: This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:18 has the following problem: removal: Package to be removed. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."maintainerless" = "warn";
|
||||
"a"."removal" = "warn";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.maintainers = [ ];
|
||||
meta.problems.removal.message = "Package will be removed.";
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:17 has the following problem: maintainerless: This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:17 has the following problem: removal: Package will be removed. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
18
pkgs/test/problems/cases/maintainerless-error/default.nix
Normal file
18
pkgs/test/problems/cases/maintainerless-error/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."maintainerless" = "error";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.maintainers = [ ];
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:16 because it has problems:
|
||||
- maintainerless: This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute.
|
||||
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
a.maintainerless = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
17
pkgs/test/problems/cases/maintainerless-ignore/default.nix
Normal file
17
pkgs/test/problems/cases/maintainerless-ignore/default.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."maintainerless" = "ignore";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ ];
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
18
pkgs/test/problems/cases/maintainerless-warn/default.nix
Normal file
18
pkgs/test/problems/cases/maintainerless-warn/default.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."maintainerless" = "warn";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.maintainers = [ ];
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:16 has the following problem: maintainerless: This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
22
pkgs/test/problems/cases/no-message/default.nix
Normal file
22
pkgs/test/problems/cases/no-message/default.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
checkMeta = true;
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.problems.removal = { };
|
||||
}
|
||||
4
pkgs/test/problems/cases/no-message/expected-stderr
Normal file
4
pkgs/test/problems/cases/no-message/expected-stderr
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:20 because it has an invalid meta attrset:
|
||||
- a.meta.problems.removal: `.message` not specified
|
||||
19
pkgs/test/problems/cases/no-problems-description/default.nix
Normal file
19
pkgs/test/problems/cases/no-problems-description/default.nix
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
21
pkgs/test/problems/cases/no-problems-fod/default.nix
Normal file
21
pkgs/test/problems/cases/no-problems-fod/default.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
outputHash = pkgs.lib.fakeHash;
|
||||
}
|
||||
1
pkgs/test/problems/cases/no-problems-fod/expected-stderr
Normal file
1
pkgs/test/problems/cases/no-problems-fod/expected-stderr
Normal file
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.teams = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
21
pkgs/test/problems/cases/no-problems/default.nix
Normal file
21
pkgs/test/problems/cases/no-problems/default.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
}
|
||||
1
pkgs/test/problems/cases/no-problems/expected-stderr
Normal file
1
pkgs/test/problems/cases/no-problems/expected-stderr
Normal file
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
21
pkgs/test/problems/cases/non-attrs-problem/default.nix
Normal file
21
pkgs/test/problems/cases/non-attrs-problem/default.nix
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
checkMeta = true;
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems.florp = true;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:19 because it has an invalid meta attrset:
|
||||
- a.meta.problems.florp: Invalid value; expected attrs, got
|
||||
true
|
||||
20
pkgs/test/problems/cases/package-name-matcher/default.nix
Normal file
20
pkgs/test/problems/cases/package-name-matcher/default.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
name = "b";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Failed assertions:
|
||||
- There is a problems.matchers with `package = "a"` and `name = "b". Use the following instead:
|
||||
problems.handlers.a.b = "error";
|
||||
28
pkgs/test/problems/cases/problem-urls/default.nix
Normal file
28
pkgs/test/problems/cases/problem-urls/default.nix
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.matchers = [
|
||||
{
|
||||
package = "a";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
meta.problems.removal = {
|
||||
message = "Removed because of XYZ.";
|
||||
urls = [
|
||||
"https://example.com"
|
||||
"https://anotherexample.com"
|
||||
];
|
||||
};
|
||||
}
|
||||
16
pkgs/test/problems/cases/problem-urls/expected-stderr
Normal file
16
pkgs/test/problems/cases/problem-urls/expected-stderr
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:20 because it has problems:
|
||||
- removal: Removed because of XYZ. (https://example.com, https://anotherexample.com)
|
||||
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
a.removal = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
17
pkgs/test/problems/cases/removal-error/default.nix
Normal file
17
pkgs/test/problems/cases/removal-error/default.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers.a.removal = "error";
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems = {
|
||||
removal.message = "This package has been abandoned upstream and will be removed.";
|
||||
};
|
||||
}
|
||||
16
pkgs/test/problems/cases/removal-error/expected-stderr
Normal file
16
pkgs/test/problems/cases/removal-error/expected-stderr
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:13 because it has problems:
|
||||
- removal: This package has been abandoned upstream and will be removed.
|
||||
|
||||
See also https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
To allow evaluation regardless, use:
|
||||
- Nixpkgs import: import nixpkgs { config = <below code>; }
|
||||
- NixOS: nixpkgs.config = <below code>;
|
||||
- nix-* commands: Put below code in ~/.config/nixpkgs/config.nix
|
||||
|
||||
{
|
||||
problems.handlers = {
|
||||
a.removal = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
17
pkgs/test/problems/cases/removal-ignore/default.nix
Normal file
17
pkgs/test/problems/cases/removal-ignore/default.nix
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
problems.handlers = {
|
||||
"a"."removal" = "ignore";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.problems.removal.message = "To be removed";
|
||||
}
|
||||
1
pkgs/test/problems/cases/removal-ignore/expected-stderr
Normal file
1
pkgs/test/problems/cases/removal-ignore/expected-stderr
Normal file
|
|
@ -0,0 +1 @@
|
|||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
22
pkgs/test/problems/cases/removal-twice-error/default.nix
Normal file
22
pkgs/test/problems/cases/removal-twice-error/default.nix
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config.checkMeta = true;
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.description = "Some package";
|
||||
meta.problems = {
|
||||
removal = {
|
||||
message = "This package has been abandoned upstream and will be removed";
|
||||
};
|
||||
removal2 = {
|
||||
kind = "removal";
|
||||
message = "This package has been abandoned upstream and will be removed2";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
|
||||
|
||||
error: Refusing to evaluate package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:12 because it has an invalid meta attrset:
|
||||
- a.meta.problems: Problem kind removal should be unique, but is used for these problems: removal, removal2
|
||||
14
pkgs/test/problems/cases/removal-warn/default.nix
Normal file
14
pkgs/test/problems/cases/removal-warn/default.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = { };
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.problems.removal.message = "Package to be removed.";
|
||||
}
|
||||
2
pkgs/test/problems/cases/removal-warn/expected-stderr
Normal file
2
pkgs/test/problems/cases/removal-warn/expected-stderr
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
evaluation warning: Package 'a-0' in /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-default.nix:11 has the following problem: removal: Package to be removed. See https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
60
pkgs/test/problems/default.nix
Normal file
60
pkgs/test/problems/default.nix
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
lib,
|
||||
nix,
|
||||
runCommand,
|
||||
removeReferencesTo,
|
||||
path,
|
||||
gitMinimal,
|
||||
}:
|
||||
let
|
||||
nixpkgs = lib.cleanSource path;
|
||||
unitResult = import ./unit.nix { inherit lib; };
|
||||
in
|
||||
assert lib.assertMsg (unitResult == [ ])
|
||||
"problems/unit.nix failing: ${lib.generators.toPretty { } unitResult}";
|
||||
lib.mapAttrs (
|
||||
name: _:
|
||||
let
|
||||
nixFile = "${./cases + "/${name}/default.nix"}";
|
||||
result = runCommand "test-problems-${name}" { nativeBuildInputs = [ removeReferencesTo ]; } ''
|
||||
export NIX_STATE_DIR=$(mktemp -d)
|
||||
mkdir $out
|
||||
|
||||
command=(
|
||||
# FIXME: Using this version because it doesn't print a trace by default
|
||||
# Probably should have some regex-style error matching instead
|
||||
"${lib.getBin nix}/bin/nix-instantiate"
|
||||
${nixFile}
|
||||
# Readonly mode because we don't need to write anything to the store
|
||||
"--readonly-mode"
|
||||
"--arg"
|
||||
"nixpkgs"
|
||||
"${nixpkgs}"
|
||||
)
|
||||
|
||||
echo "''${command[*]@Q}" > $out/command
|
||||
echo "Running ''${command[*]@Q}"
|
||||
set +e
|
||||
"''${command[@]}" >$out/stdout 2>$out/stderr
|
||||
set +e
|
||||
echo "$?" > $out/code
|
||||
echo "Command exited with code $(<$out/code)"
|
||||
remove-references-to -t ${nixFile} $out/stderr
|
||||
if grep '(stack trace truncated.*)' $out/stderr; then
|
||||
sed -i -n '/(stack trace truncated.*)/,$ p' $out/stderr
|
||||
fi
|
||||
sed -i 's/^ //' $out/stderr
|
||||
'';
|
||||
checker = runCommand "test-problems-check-${name}" { } ''
|
||||
if ! PAGER=cat ${lib.getExe gitMinimal} diff --no-index ${
|
||||
./cases + "/${name}/expected-stderr"
|
||||
} ${result}/stderr ; then
|
||||
echo "Output of $(< ${result}/command) does not match what was expected. To adapt:"
|
||||
echo "cp ${result}/stderr ${lib.path.removePrefix path ./cases + "/${name}/expected-stderr"}"
|
||||
exit 1
|
||||
fi
|
||||
touch $out
|
||||
'';
|
||||
in
|
||||
checker
|
||||
) (builtins.readDir ./cases)
|
||||
153
pkgs/test/problems/unit.nix
Normal file
153
pkgs/test/problems/unit.nix
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
{ lib }:
|
||||
let
|
||||
p = import ../../stdenv/generic/problems.nix { inherit lib; };
|
||||
|
||||
genHandlerTest =
|
||||
let
|
||||
slowReference =
|
||||
config: package: name: kind:
|
||||
# Try to find an explicit handler
|
||||
(config.problems.handlers.${package} or { }).${name}
|
||||
# Fall back, iterating through the matchers
|
||||
or (lib.pipe config.problems.matchers [
|
||||
# Find matches
|
||||
(lib.filter (
|
||||
matcher:
|
||||
(matcher.name != null -> name == matcher.name)
|
||||
&& (matcher.kind != null -> kind == matcher.kind)
|
||||
&& (matcher.package != null -> package == matcher.package)
|
||||
))
|
||||
# Extract handler level
|
||||
(map (matcher: matcher.handler))
|
||||
# Take the strongest matched handler level
|
||||
(lib.foldl' p.handlers.max "ignore")
|
||||
]);
|
||||
|
||||
genValue =
|
||||
f:
|
||||
map
|
||||
(
|
||||
package:
|
||||
map
|
||||
(
|
||||
name:
|
||||
map (kind: f package name kind) [
|
||||
"k1"
|
||||
"k2"
|
||||
"k3"
|
||||
]
|
||||
)
|
||||
[
|
||||
"n1"
|
||||
"n2"
|
||||
"n3"
|
||||
]
|
||||
)
|
||||
[
|
||||
"p1"
|
||||
"p2"
|
||||
"p3"
|
||||
];
|
||||
|
||||
in
|
||||
v: {
|
||||
expr = genValue (p.genHandlerSwitch { problems = v; }).handlerForProblem;
|
||||
expected = genValue (slowReference {
|
||||
problems = v;
|
||||
});
|
||||
};
|
||||
in
|
||||
lib.runTests {
|
||||
testHandlersLessThan =
|
||||
let
|
||||
levels = p.handlers.levels;
|
||||
slowReference =
|
||||
a: b:
|
||||
lib.lists.findFirstIndex (v: v == a) (abort "Shouldn't happen") levels
|
||||
< lib.lists.findFirstIndex (v: v == b) (abort "Shouldn't happen") levels;
|
||||
|
||||
genValue =
|
||||
f:
|
||||
lib.genList (
|
||||
i: lib.genList (j: f (lib.elemAt levels i) (lib.elemAt levels j)) (lib.length levels)
|
||||
) (lib.length levels);
|
||||
in
|
||||
{
|
||||
expr = genValue p.handlers.lessThan;
|
||||
expected = genValue slowReference;
|
||||
};
|
||||
|
||||
testHandlerEmpty = genHandlerTest {
|
||||
matchers = [ ];
|
||||
handlers = { };
|
||||
};
|
||||
|
||||
testHandlerNameSpecificHandlers = genHandlerTest {
|
||||
matchers = [ ];
|
||||
handlers.p1.n1 = "error";
|
||||
handlers.p1.n2 = "warn";
|
||||
handlers.p1.n3 = "ignore";
|
||||
};
|
||||
|
||||
testHandlerPackageSpecificHandlers = genHandlerTest {
|
||||
matchers = [ ];
|
||||
handlers.p1.n1 = "error";
|
||||
handlers.p2.n1 = "warn";
|
||||
handlers.p3.n1 = "ignore";
|
||||
};
|
||||
|
||||
testHandlersOverrideMatchers = genHandlerTest {
|
||||
matchers = [
|
||||
{
|
||||
package = "p1";
|
||||
name = "n1";
|
||||
kind = null;
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
handlers.p1.n1 = "warn";
|
||||
};
|
||||
|
||||
testMatchersDefault = genHandlerTest {
|
||||
matchers = [
|
||||
# Everything should warn by default
|
||||
{
|
||||
package = null;
|
||||
name = null;
|
||||
kind = null;
|
||||
handler = "warn";
|
||||
}
|
||||
];
|
||||
handlers = { };
|
||||
};
|
||||
|
||||
testMatchersComplicated = genHandlerTest {
|
||||
matchers = [
|
||||
{
|
||||
package = "p1";
|
||||
name = null;
|
||||
kind = null;
|
||||
handler = "warn";
|
||||
}
|
||||
{
|
||||
package = "p1";
|
||||
name = "n1";
|
||||
kind = null;
|
||||
handler = "error";
|
||||
}
|
||||
{
|
||||
package = "p1";
|
||||
name = null;
|
||||
kind = "k1";
|
||||
handler = "error";
|
||||
}
|
||||
{
|
||||
package = "p1";
|
||||
name = "n2";
|
||||
kind = "k2";
|
||||
handler = "error";
|
||||
}
|
||||
];
|
||||
handlers = { };
|
||||
};
|
||||
}
|
||||
|
|
@ -45,11 +45,18 @@ let
|
|||
internal = true;
|
||||
};
|
||||
|
||||
# Should be replaced by importing <nixos/modules/misc/assertions.nix> in the future
|
||||
# see also https://github.com/NixOS/nixpkgs/pull/207187
|
||||
warnings = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
internal = true;
|
||||
};
|
||||
assertions = mkOption {
|
||||
type = types.listOf types.anything;
|
||||
default = [ ];
|
||||
internal = true;
|
||||
};
|
||||
|
||||
# Config options
|
||||
|
||||
|
|
@ -448,6 +455,8 @@ let
|
|||
compatibility of configurations with 26.05.
|
||||
'';
|
||||
};
|
||||
|
||||
problems = (import ../stdenv/generic/problems.nix { inherit lib; }).configOptions;
|
||||
};
|
||||
|
||||
in
|
||||
|
|
@ -470,9 +479,35 @@ in
|
|||
inherit options;
|
||||
|
||||
config = {
|
||||
warnings = optionals config.warnUndeclaredOptions (
|
||||
mapAttrsToList (k: v: "undeclared Nixpkgs option set: config.${k}") config._undeclared or { }
|
||||
);
|
||||
warnings =
|
||||
optionals config.warnUndeclaredOptions (
|
||||
mapAttrsToList (k: v: "undeclared Nixpkgs option set: config.${k}") config._undeclared or { }
|
||||
)
|
||||
++ lib.optional (config.showDerivationWarnings != [ ]) ''
|
||||
`config.showDerivationWarnings = [ "maintainerless" ]` is deprecated, use `config.problems` instead:
|
||||
|
||||
config.problems.matchers = [ { kind = "maintainerless"; handler = "warn"; } ];
|
||||
|
||||
See this page for more details: https://nixos.org/manual/nixpkgs/unstable#sec-problems
|
||||
'';
|
||||
|
||||
assertions =
|
||||
# Collect the assertions from the problems.matchers.* submodules, propagate them into here
|
||||
lib.concatMap (matcher: matcher.assertions) config.problems.matchers;
|
||||
|
||||
# Put the default value for matchers in here (as in, not as an *actual* mkDefault default value),
|
||||
# to force it being merged with any custom values instead of being overridden.
|
||||
problems.matchers = [
|
||||
# Be loud and clear about package removals
|
||||
{
|
||||
kind = "removal";
|
||||
handler = "warn";
|
||||
}
|
||||
(lib.mkIf (lib.elem "maintainerless" config.showDerivationWarnings) {
|
||||
kind = "maintainerless";
|
||||
handler = "warn";
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,16 @@ let
|
|||
};
|
||||
|
||||
# take all the rest as-is
|
||||
config = lib.showWarnings configEval.config.warnings configEval.config;
|
||||
config =
|
||||
let
|
||||
failedAssertionsString = lib.concatMapStringsSep "\n" (x: "- ${x.message}") (
|
||||
lib.filter (x: !x.assertion) configEval.config.assertions
|
||||
);
|
||||
in
|
||||
if failedAssertionsString != "" then
|
||||
throw "Failed assertions:\n${failedAssertionsString}"
|
||||
else
|
||||
lib.showWarnings configEval.config.warnings configEval.config;
|
||||
|
||||
# A few packages make a new package set to draw their dependencies from.
|
||||
# (Currently to get a cross tool chain, or forced-i686 package.) Rather than
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue