mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-06-05 21:03:40 +00:00
stdenv: Use meta.problems for meta.broken underneath
And add tests for it
This commit is contained in:
@@ -153,7 +153,7 @@ The list of Nix platform types for which the [Hydra](https://github.com/nixos/hy
|
||||
|
||||
### `broken` {#var-meta-broken}
|
||||
|
||||
If set to `true`, the package is marked as "broken", meaning that it won’t show up in [search.nixos.org](https://search.nixos.org/packages), and cannot be built or installed unless the environment variable [`NIXPKGS_ALLOW_BROKEN`](#opt-allowBroken) is set.
|
||||
If set to `true`, the package is marked as "broken", meaning that it won’t show up in [search.nixos.org](https://search.nixos.org/packages), and cannot be built or installed unless [explicitly allowed](#sec-allow-broken).
|
||||
Such unconditionally-broken packages should be removed from Nixpkgs eventually unless they are fixed.
|
||||
|
||||
The value of this attribute can depend on a package's arguments, including `stdenv`.
|
||||
@@ -181,6 +181,15 @@ This means that `broken` can be used to express constraints, for example:
|
||||
This makes `broken` strictly more powerful than `meta.badPlatforms`.
|
||||
However `meta.availableOn` currently examines only `meta.platforms` and `meta.badPlatforms`, so `meta.broken` does not influence the default values for optional dependencies.
|
||||
|
||||
Underneath, `meta.broken = true;` is the same as
|
||||
```nix
|
||||
{
|
||||
meta.problems.broken.message = "This package is broken.";
|
||||
}
|
||||
```
|
||||
|
||||
By specifying this manually, the error message can be customised.
|
||||
|
||||
## `knownVulnerabilities` {#var-meta-knownVulnerabilities}
|
||||
|
||||
A list of known vulnerabilities affecting the package, usually identified by CVE identifiers.
|
||||
|
||||
@@ -179,6 +179,7 @@ Currently, the following problem kinds are known (with more reserved to be added
|
||||
- "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.
|
||||
- "broken": Automatically generated for packages with `meta.broken = true`.
|
||||
|
||||
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.
|
||||
|
||||
@@ -99,8 +99,6 @@ let
|
||||
|
||||
hasBlocklistedLicense = hasListedLicense blocklist;
|
||||
|
||||
allowBroken = config.allowBroken || getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
|
||||
|
||||
allowUnsupportedSystem =
|
||||
config.allowUnsupportedSystem || getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1";
|
||||
|
||||
@@ -121,18 +119,6 @@ let
|
||||
|
||||
isMarkedBroken = attrs: attrs.meta.broken or false;
|
||||
|
||||
# Allow granular checks to allow only some broken packages
|
||||
# Example:
|
||||
# { pkgs, ... }:
|
||||
# {
|
||||
# allowBroken = false;
|
||||
# allowBrokenPredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "hello" ];
|
||||
# }
|
||||
allowBrokenPredicate = config.allowBrokenPredicate or (x: false);
|
||||
|
||||
hasDeniedBroken =
|
||||
attrs: (attrs.meta.broken or false) && !allowBroken && !allowBrokenPredicate attrs;
|
||||
|
||||
hasUnsupportedPlatform = pkg: !(availableOn hostPlatform pkg);
|
||||
|
||||
isMarkedInsecure = attrs: (attrs.meta.knownVulnerabilities or [ ]) != [ ];
|
||||
@@ -203,7 +189,6 @@ let
|
||||
allow_attr:
|
||||
{
|
||||
Unfree = "NIXPKGS_ALLOW_UNFREE";
|
||||
Broken = "NIXPKGS_ALLOW_BROKEN";
|
||||
UnsupportedSystem = "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM";
|
||||
NonSource = "NIXPKGS_ALLOW_NONSOURCE";
|
||||
}
|
||||
@@ -212,7 +197,6 @@ let
|
||||
allow_attr:
|
||||
{
|
||||
Unfree = "unfree packages";
|
||||
Broken = "broken packages";
|
||||
UnsupportedSystem = "packages that are unsupported for this system";
|
||||
NonSource = "packages not built from source";
|
||||
}
|
||||
@@ -357,6 +341,7 @@ let
|
||||
pkgConfigModules = listOf str;
|
||||
inherit platforms;
|
||||
hydraPlatforms = listOf str;
|
||||
# Automatically turns into meta.problems.broken, see ./problems.nix
|
||||
broken = bool;
|
||||
unfree = bool;
|
||||
unsupported = bool;
|
||||
@@ -453,12 +438,6 @@ let
|
||||
msg = "contains elements not built from source (‘${showSourceType attrs.meta.sourceProvenance}’)";
|
||||
remediation = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate" attrs);
|
||||
}
|
||||
else if hasDeniedBroken attrs then
|
||||
{
|
||||
reason = "broken";
|
||||
msg = "is marked as broken";
|
||||
remediation = remediate_allowlist "Broken" "";
|
||||
}
|
||||
else if hasUnsupportedPlatform attrs && !allowUnsupportedSystem then
|
||||
let
|
||||
toPretty' = toPretty {
|
||||
|
||||
@@ -78,6 +78,7 @@ rec {
|
||||
manual = [
|
||||
"removal"
|
||||
"deprecated"
|
||||
"broken"
|
||||
];
|
||||
# Problem kinds that are currently only allowed to be specified once
|
||||
unique = [
|
||||
@@ -101,7 +102,7 @@ rec {
|
||||
# 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:
|
||||
config: attrs:
|
||||
# Order of checks optimised for short-circuiting the common case of having maintainers
|
||||
(attrs.meta.maintainers or [ ] == [ ])
|
||||
&& (attrs.meta.teams or [ ] == [ ])
|
||||
@@ -109,13 +110,26 @@ rec {
|
||||
&& (attrs ? meta.description);
|
||||
value.message = "This package has no declared maintainer, i.e. an empty `meta.maintainers` and `meta.teams` attribute.";
|
||||
}
|
||||
{
|
||||
kindName = "broken";
|
||||
condition =
|
||||
config:
|
||||
let
|
||||
# TODO: Consider deprecating this or making it generic for all problems
|
||||
allowBroken = config.allowBroken || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
|
||||
|
||||
allowBrokenPredicate = config.allowBrokenPredicate or (x: false);
|
||||
in
|
||||
attrs: attrs.meta.broken or false && !allowBroken && !allowBrokenPredicate attrs;
|
||||
value.message = "This package is broken.";
|
||||
}
|
||||
];
|
||||
|
||||
genAutomaticProblems =
|
||||
attrs:
|
||||
config: attrs:
|
||||
listToAttrs (
|
||||
map (problem: lib.nameValuePair problem.kindName problem.value) (
|
||||
filter (problem: problem.condition attrs) automaticProblems
|
||||
filter (problem: problem.condition config attrs) automaticProblems
|
||||
)
|
||||
);
|
||||
|
||||
@@ -419,6 +433,10 @@ rec {
|
||||
inherit (genHandlerSwitch config)
|
||||
handlerForProblem
|
||||
;
|
||||
# Makes sure that automatic problems can cache with just config applied
|
||||
automaticProblemsConfigCache = map (
|
||||
problem: problem // { condition = problem.condition config; }
|
||||
) automaticProblems;
|
||||
in
|
||||
attrs:
|
||||
let
|
||||
@@ -431,7 +449,7 @@ rec {
|
||||
all (
|
||||
problem:
|
||||
problem.condition attrs -> handlerForProblem pname problem.kindName problem.kindName == "ignore"
|
||||
) automaticProblems
|
||||
) automaticProblemsConfigCache
|
||||
&& (
|
||||
# No manual problems
|
||||
manualProblems == { }
|
||||
@@ -445,7 +463,7 @@ rec {
|
||||
else
|
||||
# Slow path, only here we actually figure out which problems we need to handle
|
||||
let
|
||||
problems = attrs.meta.problems or { } // genAutomaticProblems attrs;
|
||||
problems = attrs.meta.problems or { } // genAutomaticProblems config attrs;
|
||||
problemsToHandle = filter (v: v.handler != "ignore") (
|
||||
mapAttrsToList (name: problem: rec {
|
||||
inherit name;
|
||||
|
||||
15
pkgs/test/problems/cases/allow-broken-env/default.nix
Normal file
15
pkgs/test/problems/cases/allow-broken-env/default.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = { };
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
meta.broken = true;
|
||||
}
|
||||
3
pkgs/test/problems/cases/allow-broken-env/env.nix
Normal file
3
pkgs/test/problems/cases/allow-broken-env/env.nix
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
NIXPKGS_ALLOW_BROKEN = 1;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
@@ -0,0 +1,18 @@
|
||||
{ nixpkgs }:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
allowBrokenPredicate = attrs: lib.getName attrs == "a";
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
meta.broken = true;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
@@ -0,0 +1,18 @@
|
||||
{ nixpkgs }:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
allowBrokenPredicate = attrs: lib.getName attrs == "b";
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
meta.broken = true;
|
||||
}
|
||||
@@ -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:
|
||||
- broken: This package is broken.
|
||||
|
||||
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.broken = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
17
pkgs/test/problems/cases/allow-broken/default.nix
Normal file
17
pkgs/test/problems/cases/allow-broken/default.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
{ nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [ ];
|
||||
config = {
|
||||
allowBroken = true;
|
||||
};
|
||||
};
|
||||
in
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
pname = "a";
|
||||
version = "0";
|
||||
meta.maintainers = [ "hello" ];
|
||||
meta.description = "Some package";
|
||||
meta.broken = true;
|
||||
}
|
||||
1
pkgs/test/problems/cases/allow-broken/expected-stderr
Normal file
1
pkgs/test/problems/cases/allow-broken/expected-stderr
Normal file
@@ -0,0 +1 @@
|
||||
warning: you did not specify '--add-root'; the result might be removed by the garbage collector
|
||||
14
pkgs/test/problems/cases/broken-manual/default.nix
Normal file
14
pkgs/test/problems/cases/broken-manual/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.description = "Some package";
|
||||
meta.problems.broken.message = "This package is broken because horse.";
|
||||
}
|
||||
16
pkgs/test/problems/cases/broken-manual/expected-stderr
Normal file
16
pkgs/test/problems/cases/broken-manual/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:12 because it has problems:
|
||||
- broken: This package is broken because horse.
|
||||
|
||||
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.broken = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
14
pkgs/test/problems/cases/broken/default.nix
Normal file
14
pkgs/test/problems/cases/broken/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.description = "Some package";
|
||||
meta.broken = true;
|
||||
}
|
||||
16
pkgs/test/problems/cases/broken/expected-stderr
Normal file
16
pkgs/test/problems/cases/broken/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:12 because it has problems:
|
||||
- broken: This package is broken.
|
||||
|
||||
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.broken = "warn"; # or "ignore"
|
||||
};
|
||||
}
|
||||
@@ -1,4 +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`
|
||||
- a.meta.problems.invalid: Problem kind invalid, inferred from the problem name, is invalid; expected enum<removal,deprecated,broken>. You can specify an explicit problem kind with `a.meta.problems.invalid.kind`
|
||||
|
||||
@@ -20,7 +20,17 @@ lib.mapAttrs (
|
||||
export NIX_STATE_DIR=$(mktemp -d)
|
||||
mkdir $out
|
||||
|
||||
command=(
|
||||
|
||||
command=()
|
||||
${lib.optionalString (builtins.pathExists (./cases + "/${name}/env.nix")) ''
|
||||
command+=(
|
||||
env
|
||||
${lib.concatMapAttrsStringSep "\n" (name: value: "${name}=${toString value}") (
|
||||
import (./cases + "/${name}/env.nix")
|
||||
)}
|
||||
)
|
||||
''}
|
||||
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"
|
||||
|
||||
@@ -498,6 +498,10 @@ in
|
||||
# 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 = [
|
||||
{
|
||||
kind = "broken";
|
||||
handler = "error";
|
||||
}
|
||||
# Be loud and clear about package removals
|
||||
{
|
||||
kind = "removal";
|
||||
|
||||
Reference in New Issue
Block a user