From 42cfcdf4e731f5cdcbb7ad4e3fc01d0f62121acb Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 1 Dec 2025 15:50:25 +0100 Subject: [PATCH 1/6] check-meta.nix: Refactor to inlinie remediations - Makes the code more clean and obvious - Allows remediations to depend on values computed during the check (useful for https://github.com/NixOS/nixpkgs/pull/338267) --- pkgs/stdenv/generic/check-meta.nix | 33 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index b99f2531831c5..abfca2adc449e 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -197,17 +197,6 @@ let pos_str = meta: meta.position or "«unknown-file»"; - remediation = { - unfree = remediate_allowlist "Unfree" (remediate_predicate "allowUnfreePredicate"); - non-source = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate"); - broken = remediate_allowlist "Broken" (x: ""); - unsupported = remediate_allowlist "UnsupportedSystem" (x: ""); - blocklisted = x: ""; - insecure = remediate_insecure; - broken-outputs = remediateOutputsToInstall; - unknown-meta = x: ""; - maintainerless = x: ""; - }; remediation_env_var = allow_attr: { @@ -317,6 +306,7 @@ let { reason, errormsg ? "", + remediation, }: let msg = @@ -327,7 +317,7 @@ let Package ‘${getNameWithVersion attrs}’ in ${pos_str meta} ${errormsg}, refusing to evaluate. '' - + (builtins.getAttr reason remediation) attrs; + + remediation; handler = if config ? handleEvalIssue then config.handleEvalIssue reason else throw; in @@ -338,15 +328,15 @@ let { reason, errormsg ? "", + remediation, }: let - remediationMsg = (builtins.getAttr reason remediation) attrs; msg = if inHydra then "Warning while evaluating ${getNameWithVersion attrs}: «${reason}»: ${errormsg}" else "Package ${getNameWithVersion attrs} in ${pos_str meta} ${errormsg}, continuing anyway." - + (optionalString (remediationMsg != "") "\n${remediationMsg}"); + + (optionalString (remediation != "") "\n${remediation}"); isEnabled = findFirst (x: x == reason) null showWarnings; in if isEnabled != null then builtins.trace msg true else true; @@ -484,7 +474,7 @@ let # e.g brokenness or license. # # Return { valid: "yes", "warn" or "no" } and additionally - # { reason: String; errormsg: String } if it is not valid, where + # { reason: String; errormsg: String, remediation: String } if it is not valid, where # reason is one of "unfree", "blocklisted", "broken", "insecure", ... # !!! reason strings are hardcoded into OfBorg, make sure to keep them in sync # Along with a boolean flag for each reason @@ -506,6 +496,7 @@ let valid = "no"; reason = "unknown-meta"; errormsg = "has an invalid meta attrset:${concatMapStrings (x: "\n - " + x) res}\n"; + remediation = ""; } # --- Put checks that cannot be ignored here --- @@ -514,6 +505,7 @@ let valid = "no"; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; + remediation = remediateOutputsToInstall attrs; } # --- Put checks that can be ignored here --- @@ -522,24 +514,28 @@ let valid = "no"; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; + remediation = remediate_allowlist "Unfree" (remediate_predicate "allowUnfreePredicate") attrs; } else if hasBlocklistedLicense attrs then { valid = "no"; reason = "blocklisted"; errormsg = "has a blocklisted license (‘${showLicense attrs.meta.license}’)"; + remediation = ""; } else if hasDeniedNonSourceProvenance attrs then { valid = "no"; reason = "non-source"; errormsg = "contains elements not built from source (‘${showSourceType attrs.meta.sourceProvenance}’)"; + remediation = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate") attrs; } else if hasDeniedBroken attrs then { valid = "no"; reason = "broken"; errormsg = "is marked as broken"; + remediation = remediate_allowlist "Broken" (x: ""); } else if !allowUnsupportedSystem && hasUnsupportedPlatform attrs then let @@ -557,12 +553,14 @@ let package.meta.platforms = ${toPretty' (attrs.meta.platforms or [ ])} package.meta.badPlatforms = ${toPretty' (attrs.meta.badPlatforms or [ ])} ''; + remediation = remediate_allowlist "UnsupportedSystem" (x: "") attrs; } else if !(hasAllowedInsecure attrs) then { valid = "no"; reason = "insecure"; errormsg = "is marked as insecure"; + remediation = remediate_insecure attrs; } # --- warnings --- @@ -572,6 +570,7 @@ let valid = "warn"; reason = "maintainerless"; errormsg = "has no maintainers or teams"; + remediation = ""; } # ----- else @@ -752,9 +751,9 @@ let if valid == "yes" then true else if valid == "no" then - (handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg; }) + (handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg remediation; }) else if valid == "warn" then - (handleEvalWarning { inherit meta attrs; } { inherit (validity) reason errormsg; }) + (handleEvalWarning { inherit meta attrs; } { inherit (validity) reason errormsg remediation; }) else throw "Unknown validity: '${valid}'" ); From 360f401244eb170a85791e3e77a98c6b4b912fad Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 1 Dec 2025 15:55:41 +0100 Subject: [PATCH 2/6] check-meta.nix: Optimise by avoiding double attribute Probably that's a historical artifact --- pkgs/stdenv/generic/check-meta.nix | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index abfca2adc449e..a5913c8a2e28a 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -302,8 +302,9 @@ let ''; handleEvalIssue = - { meta, attrs }: { + meta, + attrs, reason, errormsg ? "", remediation, @@ -324,8 +325,9 @@ let handler msg; handleEvalWarning = - { meta, attrs }: { + meta, + attrs, reason, errormsg ? "", remediation, @@ -751,9 +753,15 @@ let if valid == "yes" then true else if valid == "no" then - (handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg remediation; }) + (handleEvalIssue { + inherit meta attrs; + inherit (validity) reason errormsg remediation; + }) else if valid == "warn" then - (handleEvalWarning { inherit meta attrs; } { inherit (validity) reason errormsg remediation; }) + (handleEvalWarning { + inherit meta attrs; + inherit (validity) reason errormsg remediation; + }) else throw "Unknown validity: '${valid}'" ); From 43f81c8e08c7c8c7a7848a5e8ea73972c1f0f67a Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 1 Dec 2025 19:19:22 +0100 Subject: [PATCH 3/6] check-meta.nix: Refactor for better use of parenthesis Remove some clearly-unnecessary ones and add some direly-needed ones --- pkgs/stdenv/generic/check-meta.nix | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index a5913c8a2e28a..6c63b5a74bdf7 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -100,7 +100,7 @@ let isUnfree = licenses: if isAttrs licenses then - !licenses.free or true + !(licenses.free or true) # TODO: Returning false in the case of a string is a bug that should be fixed. # In a previous implementation of this function the function body # was `licenses: lib.lists.any (l: !l.free or true) licenses;` @@ -108,7 +108,7 @@ let else if isString licenses then false else - any (l: !l.free or true) licenses; + any (l: !(l.free or true)) licenses; hasUnfreeLicense = attrs: hasLicense attrs && isUnfree attrs.meta.license; @@ -173,7 +173,7 @@ let isNonSource = sourceTypes: any (t: !t.isSource) sourceTypes; hasNonSourceProvenance = - attrs: (attrs ? meta.sourceProvenance) && isNonSource attrs.meta.sourceProvenance; + attrs: attrs ? meta.sourceProvenance && isNonSource attrs.meta.sourceProvenance; # Allow granular checks to allow only some non-source-built packages # Example: @@ -753,15 +753,15 @@ let if valid == "yes" then true else if valid == "no" then - (handleEvalIssue { + handleEvalIssue { inherit meta attrs; inherit (validity) reason errormsg remediation; - }) + } else if valid == "warn" then - (handleEvalWarning { + handleEvalWarning { inherit meta attrs; inherit (validity) reason errormsg remediation; - }) + } else throw "Unknown validity: '${valid}'" ); From ab0c4c104ce12eca28168e1893a2e230e396a028 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 1 Dec 2025 19:20:20 +0100 Subject: [PATCH 4/6] check-meta.nix: Minor performance optimisiations - Avoid some attribute set accesses - Make a variable more local, avoiding a thunk - Avoid always checking config.checkMeta for every attribute --- pkgs/stdenv/generic/check-meta.nix | 65 ++++++++++++++++-------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 6c63b5a74bdf7..dca318a338ba3 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -15,15 +15,15 @@ let concatMapStrings concatMapStringsSep concatStrings + filter findFirst + getName isDerivation length concatMap mutuallyExclusive optional - optionalAttrs optionalString - optionals isAttrs isString mapAttrs @@ -47,6 +47,11 @@ let toPretty ; + inherit (builtins) + getEnv + trace + ; + # 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; @@ -57,11 +62,11 @@ let getNameWithVersion = attrs: attrs.name or "${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}"; - allowUnfree = config.allowUnfree || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1"; + allowUnfree = config.allowUnfree || getEnv "NIXPKGS_ALLOW_UNFREE" == "1"; allowNonSource = let - envVar = builtins.getEnv "NIXPKGS_ALLOW_NONSOURCE"; + envVar = getEnv "NIXPKGS_ALLOW_NONSOURCE"; in if envVar != "" then envVar != "0" else config.allowNonSource or true; @@ -92,10 +97,10 @@ let hasBlocklistedLicense = attrs: hasListedLicense blocklist attrs; - allowBroken = config.allowBroken || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1"; + allowBroken = config.allowBroken || getEnv "NIXPKGS_ALLOW_BROKEN" == "1"; allowUnsupportedSystem = - config.allowUnsupportedSystem || builtins.getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1"; + config.allowUnsupportedSystem || getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1"; isUnfree = licenses: @@ -161,14 +166,12 @@ let attrs: hasUnfreeLicense attrs && !allowUnfree && !allowUnfreePredicate attrs; allowInsecureDefaultPredicate = - x: builtins.elem (getNameWithVersion x) (config.permittedInsecurePackages or [ ]); - allowInsecurePredicate = x: (config.allowInsecurePredicate or allowInsecureDefaultPredicate) x; + x: elem (getNameWithVersion x) (config.permittedInsecurePackages or [ ]); + allowInsecurePredicate = config.allowInsecurePredicate or allowInsecureDefaultPredicate; hasAllowedInsecure = attrs: - !(isMarkedInsecure attrs) - || allowInsecurePredicate attrs - || builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1"; + !(isMarkedInsecure attrs) || allowInsecurePredicate attrs || getEnv "NIXPKGS_ALLOW_INSECURE" == "1"; isNonSource = sourceTypes: any (t: !t.isSource) sourceTypes; @@ -219,7 +222,7 @@ let Alternatively you can configure a predicate to allow specific packages: { nixpkgs.config.${predicateConfigAttr} = pkg: builtins.elem (lib.getName pkg) [ - "${lib.getName attrs}" + "${getName attrs}" ]; } ''; @@ -289,7 +292,7 @@ let let expectedOutputs = attrs.meta.outputsToInstall or [ ]; actualOutputs = attrs.outputs or [ "out" ]; - missingOutputs = builtins.filter (output: !builtins.elem output actualOutputs) expectedOutputs; + missingOutputs = filter (output: !elem output actualOutputs) expectedOutputs; in '' The package ${getNameWithVersion attrs} has set meta.outputsToInstall to: ${builtins.concatStringsSep ", " expectedOutputs} @@ -332,16 +335,18 @@ let errormsg ? "", remediation, }: - let - msg = - if inHydra then - "Warning while evaluating ${getNameWithVersion attrs}: «${reason}»: ${errormsg}" - else - "Package ${getNameWithVersion attrs} in ${pos_str meta} ${errormsg}, continuing anyway." - + (optionalString (remediation != "") "\n${remediation}"); - isEnabled = findFirst (x: x == reason) null showWarnings; - in - if isEnabled != null then builtins.trace msg true else true; + if elem reason showWarnings then + let + msg = + if inHydra then + "Warning while evaluating ${getNameWithVersion attrs}: «${reason}»: ${errormsg}" + else + "Package ${getNameWithVersion attrs} in ${pos_str meta} ${errormsg}, continuing anyway." + + (optionalString (remediation != "") "\n${remediation}"); + in + trace msg true + else + true; metaTypes = let @@ -460,17 +465,19 @@ let }]" ]; checkMeta = - meta: - optionals config.checkMeta (concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta)); + if config.checkMeta then + meta: concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta) + else + meta: [ ]; checkOutputsToInstall = attrs: let expectedOutputs = attrs.meta.outputsToInstall or [ ]; actualOutputs = attrs.outputs or [ "out" ]; - missingOutputs = builtins.filter (output: !builtins.elem output actualOutputs) expectedOutputs; + missingOutputs = filter (output: !elem output actualOutputs) expectedOutputs; in - if config.checkMeta then builtins.length missingOutputs > 0 else false; + if config.checkMeta then length missingOutputs > 0 else false; # Check if a derivation is valid, that is whether it passes checks for # e.g brokenness or license. @@ -731,9 +738,7 @@ let available = validity.valid != "no" - && ( - if config.checkMetaRecursively or false then all (d: d.meta.available or true) references else true - ); + && ((config.checkMetaRecursively or false) -> all (d: d.meta.available or true) references); }; assertValidity = From f7486d2a6383acfa883f672febdaaa1380624de6 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 1 Dec 2025 20:00:16 +0100 Subject: [PATCH 5/6] check-meta.nix: More performance optimisations - Boolean operator short-circuit optimisation - Eta-reduction and make some allow/blocklist-dependend functions more cachable - Inline functions that are only used once - Make getEnv cached --- pkgs/stdenv/generic/check-meta.nix | 64 +++++++++++++++--------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index dca318a338ba3..6e22e123cd0e3 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -79,23 +79,24 @@ let else throw "allowlistedLicenses and blocklistedLicenses are not mutually exclusive."; - hasLicense = attrs: attrs ? meta.license; - hasListedLicense = assert areLicenseListsValid; - list: attrs: - length list > 0 - && hasLicense attrs - && ( - if isList attrs.meta.license then - any (l: elem l list) attrs.meta.license - else - elem attrs.meta.license list - ); + list: + if list == [ ] then + attrs: false + else + attrs: + attrs ? meta.license + && ( + if isList attrs.meta.license then + any (l: elem l list) attrs.meta.license + else + elem attrs.meta.license list + ); - hasAllowlistedLicense = attrs: hasListedLicense allowlist attrs; + hasAllowlistedLicense = hasListedLicense allowlist; - hasBlocklistedLicense = attrs: hasListedLicense blocklist attrs; + hasBlocklistedLicense = hasListedLicense blocklist; allowBroken = config.allowBroken || getEnv "NIXPKGS_ALLOW_BROKEN" == "1"; @@ -115,7 +116,7 @@ let else any (l: !(l.free or true)) licenses; - hasUnfreeLicense = attrs: hasLicense attrs && isUnfree attrs.meta.license; + hasUnfreeLicense = attrs: attrs ? meta.license && isUnfree attrs.meta.license; hasNoMaintainers = # To get usable output, we want to avoid flagging "internal" derivations. @@ -169,14 +170,10 @@ let x: elem (getNameWithVersion x) (config.permittedInsecurePackages or [ ]); allowInsecurePredicate = config.allowInsecurePredicate or allowInsecureDefaultPredicate; - hasAllowedInsecure = - attrs: - !(isMarkedInsecure attrs) || allowInsecurePredicate attrs || getEnv "NIXPKGS_ALLOW_INSECURE" == "1"; - - isNonSource = sourceTypes: any (t: !t.isSource) sourceTypes; + allowInsecure = getEnv "NIXPKGS_ALLOW_INSECURE" == "1"; - hasNonSourceProvenance = - attrs: attrs ? meta.sourceProvenance && isNonSource attrs.meta.sourceProvenance; + hasDisallowedInsecure = + attrs: isMarkedInsecure attrs && !allowInsecure && !allowInsecurePredicate attrs; # Allow granular checks to allow only some non-source-built packages # Example: @@ -191,7 +188,11 @@ let # package has non-source provenance and is not explicitly allowed by the # `allowNonSourcePredicate` function. hasDeniedNonSourceProvenance = - attrs: hasNonSourceProvenance attrs && !allowNonSource && !allowNonSourcePredicate attrs; + attrs: + attrs ? meta.sourceProvenance + && any (t: !t.isSource) attrs.meta.sourceProvenance + && !allowNonSource + && !allowNonSourcePredicate attrs; showLicenseOrSourceType = value: toString (map (v: v.shortName or v.fullName or "unknown") (toList value)); @@ -471,13 +472,14 @@ let meta: [ ]; checkOutputsToInstall = - attrs: - let - expectedOutputs = attrs.meta.outputsToInstall or [ ]; - actualOutputs = attrs.outputs or [ "out" ]; - missingOutputs = filter (output: !elem output actualOutputs) expectedOutputs; - in - if config.checkMeta then length missingOutputs > 0 else false; + if config.checkMeta then + attrs: + let + actualOutputs = attrs.outputs or [ "out" ]; + in + any (output: !elem output actualOutputs) (attrs.meta.outputsToInstall or [ ]) + else + attrs: false; # Check if a derivation is valid, that is whether it passes checks for # e.g brokenness or license. @@ -546,7 +548,7 @@ let errormsg = "is marked as broken"; remediation = remediate_allowlist "Broken" (x: ""); } - else if !allowUnsupportedSystem && hasUnsupportedPlatform attrs then + else if hasUnsupportedPlatform attrs && !allowUnsupportedSystem then let toPretty' = toPretty { allowPrettyValues = true; @@ -564,7 +566,7 @@ let ''; remediation = remediate_allowlist "UnsupportedSystem" (x: "") attrs; } - else if !(hasAllowedInsecure attrs) then + else if hasDisallowedInsecure attrs then { valid = "no"; reason = "insecure"; From 660cecdc16cea8d195eba9fb6c6b0b3cbe0aa717 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 1 Dec 2025 21:56:01 +0100 Subject: [PATCH 6/6] check-meta.nix: Optimise - Remove the internal conditioning on the result of `valid`, we can know exactly when which value is produced - Faster success path for checkMeta, also avoiding an environment - Inline handlers --- pkgs/stdenv/generic/check-meta.nix | 161 +++++++++++------------------ 1 file changed, 62 insertions(+), 99 deletions(-) diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 6e22e123cd0e3..0093298ca2998 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -305,50 +305,6 @@ let ${concatStrings (map (output: " - ${output}\n") missingOutputs)} ''; - handleEvalIssue = - { - meta, - attrs, - reason, - errormsg ? "", - remediation, - }: - let - msg = - if inHydra then - "Failed to evaluate ${getNameWithVersion attrs}: «${reason}»: ${errormsg}" - else - '' - Package ‘${getNameWithVersion attrs}’ in ${pos_str meta} ${errormsg}, refusing to evaluate. - - '' - + remediation; - - handler = if config ? handleEvalIssue then config.handleEvalIssue reason else throw; - in - handler msg; - - handleEvalWarning = - { - meta, - attrs, - reason, - errormsg ? "", - remediation, - }: - if elem reason showWarnings then - let - msg = - if inHydra then - "Warning while evaluating ${getNameWithVersion attrs}: «${reason}»: ${errormsg}" - else - "Package ${getNameWithVersion attrs} in ${pos_str meta} ${errormsg}, continuing anyway." - + (optionalString (remediation != "") "\n${remediation}"); - in - trace msg true - else - true; - metaTypes = let types = import ./meta-types.nix { inherit lib; }; @@ -444,11 +400,10 @@ let identifiers = attrs; }; + # Map attrs directly to the verify function for performance + metaTypes' = mapAttrs (_: t: t.verify) metaTypes; + checkMetaAttr = - let - # Map attrs directly to the verify function for performance - metaTypes' = mapAttrs (_: t: t.verify) metaTypes; - in k: v: if metaTypes ? ${k} then if metaTypes'.${k} v then @@ -465,11 +420,14 @@ let concatMapStringsSep ", " (x: "'${x}'") (attrNames metaTypes) }]" ]; - checkMeta = + + checkMeta = meta: concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta); + + metaInvalid = if config.checkMeta then - meta: concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta) + meta: !all (attr: metaTypes ? ${attr} && metaTypes'.${attr} meta.${attr}) (attrNames meta) else - meta: [ ]; + meta: false; checkOutputsToInstall = if config.checkMeta then @@ -490,30 +448,21 @@ let # !!! reason strings are hardcoded into OfBorg, make sure to keep them in sync # Along with a boolean flag for each reason checkValidity = - let - validYes = { - valid = "yes"; - handled = true; - }; - in attrs: # Check meta attribute types first, to make sure it is always called even when there are other issues # Note that this is not a full type check and functions below still need to by careful about their inputs! - let - res = checkMeta (attrs.meta or { }); - in - if res != [ ] then + if metaInvalid (attrs.meta or { }) then { - valid = "no"; reason = "unknown-meta"; - errormsg = "has an invalid meta attrset:${concatMapStrings (x: "\n - " + x) res}\n"; + errormsg = "has an invalid meta attrset:${ + concatMapStrings (x: "\n - " + x) (checkMeta attrs.meta) + }\n"; remediation = ""; } # --- Put checks that cannot be ignored here --- else if checkOutputsToInstall attrs then { - valid = "no"; reason = "broken-outputs"; errormsg = "has invalid meta.outputsToInstall"; remediation = remediateOutputsToInstall attrs; @@ -522,28 +471,24 @@ let # --- Put checks that can be ignored here --- else if hasDeniedUnfreeLicense attrs && !(hasAllowlistedLicense attrs) then { - valid = "no"; reason = "unfree"; errormsg = "has an unfree license (‘${showLicense attrs.meta.license}’)"; remediation = remediate_allowlist "Unfree" (remediate_predicate "allowUnfreePredicate") attrs; } else if hasBlocklistedLicense attrs then { - valid = "no"; reason = "blocklisted"; errormsg = "has a blocklisted license (‘${showLicense attrs.meta.license}’)"; remediation = ""; } else if hasDeniedNonSourceProvenance attrs then { - valid = "no"; reason = "non-source"; errormsg = "contains elements not built from source (‘${showSourceType attrs.meta.sourceProvenance}’)"; remediation = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate") attrs; } else if hasDeniedBroken attrs then { - valid = "no"; reason = "broken"; errormsg = "is marked as broken"; remediation = remediate_allowlist "Broken" (x: ""); @@ -556,7 +501,6 @@ let }; in { - valid = "no"; reason = "unsupported"; errormsg = '' is not available on the requested hostPlatform: @@ -568,24 +512,24 @@ let } else if hasDisallowedInsecure attrs then { - valid = "no"; reason = "insecure"; errormsg = "is marked as insecure"; remediation = remediate_insecure attrs; } + else + null; - # --- warnings --- - # Please also update the type in /pkgs/top-level/config.nix alongside this. - else if hasNoMaintainers attrs then + # Please also update the type in /pkgs/top-level/config.nix alongside this. + checkWarnings = + attrs: + if hasNoMaintainers attrs then { - valid = "warn"; reason = "maintainerless"; errormsg = "has no maintainers or teams"; remediation = ""; } - # ----- else - validYes; + null; # Helper functions and declarations to handle identifiers, extracted to reduce allocations hasAllCPEParts = @@ -743,35 +687,54 @@ let && ((config.checkMetaRecursively or false) -> all (d: d.meta.available or true) references); }; + validYes = { + valid = "yes"; + handled = true; + }; + assertValidity = { meta, attrs }: let - validity = checkValidity attrs; - inherit (validity) valid; + invalid = checkValidity attrs; + warning = checkWarnings attrs; in - if validity ? handled then - validity + if isNull invalid then + if isNull warning then + validYes + else + let + msg = + if inHydra then + "Warning while evaluating ${getNameWithVersion attrs}: «${warning.reason}»: ${warning.errormsg}" + else + "Package ${getNameWithVersion attrs} in ${pos_str meta} ${warning.errormsg}, continuing anyway." + + (optionalString (warning.remediation != "") "\n${warning.remediation}"); + + handled = if elem warning.reason showWarnings then trace msg true else true; + in + warning + // { + valid = "warn"; + handled = handled; + } else - validity - // { - # Throw an error if trying to evaluate a non-valid derivation - # or, alternatively, just output a warning message. - handled = ( - if valid == "yes" then - true - else if valid == "no" then - handleEvalIssue { - inherit meta attrs; - inherit (validity) reason errormsg remediation; - } - else if valid == "warn" then - handleEvalWarning { - inherit meta attrs; - inherit (validity) reason errormsg remediation; - } + let + msg = + if inHydra then + "Failed to evaluate ${getNameWithVersion attrs}: «${invalid.reason}»: ${invalid.errormsg}" else - throw "Unknown validity: '${valid}'" - ); + '' + Package ‘${getNameWithVersion attrs}’ in ${pos_str meta} ${invalid.errormsg}, refusing to evaluate. + + '' + + invalid.remediation; + + handled = if config ? handleEvalIssue then config.handleEvalIssue invalid.reason msg else throw msg; + in + invalid + // { + valid = "no"; + handled = handled; }; in