Commit 27dd4344 authored by Silvan Mosberger's avatar Silvan Mosberger
Browse files
parent 8fe8f0eb
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -629,6 +629,9 @@
  "chap-stdenv": [
    "index.html#chap-stdenv"
  ],
  "sec-problems": [
    "index.html#sec-problems"
  ],
  "sec-using-llvm": [
    "index.html#sec-using-llvm"
  ],
+53 −0
Original line number Diff line number Diff line
@@ -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.
+55 −67
Original line number Diff line number Diff line
@@ -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
      let
        msg =
          if inHydra then
            "Failed to evaluate ${getNameWithVersion attrs}: «${invalid.reason}»: ${invalid.msg}"
        {
          valid = if isNull problems.error then "warn" else "no";
          handled = handle {
            inherit attrs meta;
            inherit (problems) error warnings;
          };
        }
    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
+2 −2
Original line number Diff line number Diff line
@@ -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  [${
Loading