From b33529a3eedfbae31d8c0bb27523ef9932cb8a27 Mon Sep 17 00:00:00 2001 From: Tobias Mayer Date: Sun, 8 Mar 2026 11:20:11 +0100 Subject: [PATCH 1/4] Add shared ratchet infrastructure --- src/ratchet.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/ratchet.rs b/src/ratchet.rs index e977bb0c..99c07ee7 100644 --- a/src/ratchet.rs +++ b/src/ratchet.rs @@ -2,6 +2,8 @@ //! //! Each type has a `compare` method that validates the ratchet checks for that item. +use std::marker::PhantomData; + use relative_path::RelativePath; use std::collections::BTreeMap; @@ -191,3 +193,24 @@ impl ToProblem for UsesByName { } } } + +pub trait EnabledAttributeProblem { + fn introduced_problem(name: &str, file: RelativePathBuf) -> Problem; + fn regressed_problem(name: &str, file: RelativePathBuf) -> Problem; +} + +/// The ratchet value of an evaluated boolean attribute that must be enabled for new packages and +/// must not regress to `false` once enabled. +pub struct EnabledAttribute(PhantomData); + +impl ToProblem for EnabledAttribute { + type ToContext = RelativePathBuf; + + fn to_problem(name: &str, optional_from: Option<()>, file: &Self::ToContext) -> Problem { + if optional_from.is_some() { + ProblemKind::regressed_problem(name, file.clone()) + } else { + ProblemKind::introduced_problem(name, file.clone()) + } + } +} From f5e4b344406220f7e7b49ae3bf7fd43ba2a0c0bf Mon Sep 17 00:00:00 2001 From: Tobias Mayer Date: Sun, 8 Mar 2026 11:39:35 +0100 Subject: [PATCH 2/4] Prepare non-by-name evaluation for additional ratchets The next ratchets need more context than the existing by-name check alone: they must be able to report a stable source location for attributes defined outside pkgs/by-name as well. Isolate that control-flow cleanup first so the later strictDeps and __structuredAttrs commits can stay focused on behavior rather than being mixed with a larger evaluator reshaping. Co-authored-by: Michael Daniels --- src/eval.rs | 207 +++++++++++++++++++++++++----------------------- src/nix_file.rs | 2 +- 2 files changed, 109 insertions(+), 100 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 58a8c4a3..9739304c 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -455,12 +455,8 @@ fn handle_non_by_name_attribute( use NonByNameAttribute::EvalSuccess; use ratchet::RatchetState::{Loose, NonApplicable, Tight}; - // The ratchet state whether this attribute uses `pkgs/by-name`. - // - // This is never `Tight`, because we only either: - // - Know that the attribute _could_ be migrated to `pkgs/by-name`, which is `Loose` - // - Or we're unsure, in which case we use `NonApplicable` - let uses_by_name = + // The ratchet state for this package. + let package = match non_by_name_attribute { // This is a big ol' match on various properties of the attribute // // First, it needs to succeed evaluation. We can't know whether an attribute could be @@ -477,107 +473,120 @@ fn handle_non_by_name_attribute( // `pkgs/by-name` has the problem that if a package evaluation gets broken temporarily, // fixing it requires a move to pkgs/by-name, which could happen more often and isn't // really justified. - if let EvalSuccess(AttributeInfo { + EvalSuccess(AttributeInfo { // We're only interested in attributes that are attribute sets, which all derivations // are. Anything else can't be in `pkgs/by-name`. - attribute_variant: AttributeVariant::AttributeSet { - // As of today, non-derivation attribute sets can't be in `pkgs/by-name`. - is_derivation: true, - // Of the two definition variants, really only the manual one makes sense here. - // - // Special cases are: - // - // - Manual aliases to auto-called packages are not treated as manual definitions, - // due to limitations in the semantic `callPackage` detection. - // So those should be ignored. - // - // - Manual definitions using the internal `_internalCallByNamePackageFile` are - // not treated as manual definitions, since `_internalCallByNamePackageFile` is - // used to detect automatic ones. We can't distinguish from the above case, so we - // just need to ignore this one too, even if that internal attribute should never - // be called manually. - definition_variant: DefinitionVariant::ManualDefinition { - is_semantic_call_package - } - }, + attribute_variant: + AttributeVariant::AttributeSet { + // As of today, non-derivation attribute sets can't be in `pkgs/by-name`. + is_derivation: true, + // Of the two definition variants, really only the manual one makes sense + // here. + // + // Special cases are: + // + // - Manual aliases to auto-called packages are not treated as manual + // definitions, due to limitations in the semantic `callPackage` detection. + // So those should be ignored. + // + // - Manual definitions using the internal `_internalCallByNamePackageFile` + // are not treated as manual definitions, since + // `_internalCallByNamePackageFile` is used to detect automatic ones. We + // can't distinguish from the above case, so we just need to ignore this one + // too, even if that internal attribute should never be called manually. + definition_variant, + }, + location, + }) => { // We need the location of the manual definition, because otherwise we can't figure out // whether it's a syntactic `callPackage`. - location: Some(location), - }) = non_by_name_attribute { - - // Parse the Nix file in the location - let nix_file = nix_file_store.get(&location.file)?; - - // The relative location of the Nix file, for error messages - let location = location.relative(nixpkgs_path).with_context(|| { - format!("Failed to resolve the file where attribute {attribute_name} is defined") - })?; + let parsed_definition = if let Some(location) = location { + // Parse the Nix file in the location + let nix_file = nix_file_store.get(&location.file)?; + + // The relative location of the Nix file, for error messages + let location = location.relative(nixpkgs_path).with_context(|| { + format!( + "Failed to resolve the file where attribute {attribute_name} is defined" + ) + })?; + + // Figure out whether it's an attribute definition of the form + // `= callPackage `, returning the arguments if so. + let (optional_syntactic_call_package, _definition) = nix_file + .call_package_argument_info_at(location.line, location.column, nixpkgs_path) + .with_context(|| { + format!( + "Failed to get the definition info for attribute {}", + attribute_name + ) + })?; + Some((location, optional_syntactic_call_package)) + } else { + None + }; - // Figure out whether it's an attribute definition of the form - // `= callPackage `, returning the arguments if so. - let (optional_syntactic_call_package, _definition) = nix_file - .call_package_argument_info_at( - location.line, - location.column, - // Passing the Nixpkgs path here both checks that the is within Nixpkgs, - // and strips the absolute Nixpkgs path from it, such that - // syntactic_call_package.relative_path is relative to Nixpkgs - nixpkgs_path - ) - .with_context(|| { - format!("Failed to get the definition info for attribute {}", attribute_name) - })?; - - // At this point, we completed two different checks for whether it's a `callPackage`. - match (is_semantic_call_package, optional_syntactic_call_package) { - // Something like ` = { }` - (false, None) - // Something like ` = pythonPackages.callPackage ...` - | (false, Some(_)) - // Something like ` = bar` where `bar = pkgs.callPackage ...` - | (true, None) => { - // In all of these cases, it's not possible to migrate the package to - // `pkgs/by-name`. + // This is never `Tight`, because we only either: + // - Know that the attribute _could_ be migrated to `pkgs/by-name`, which is `Loose` + // - Or we're unsure, in which case we use `NonApplicable` + let uses_by_name = if let ( + DefinitionVariant::ManualDefinition { + is_semantic_call_package, + }, + Some((location, optional_syntactic_call_package)), + ) = (definition_variant, parsed_definition.as_ref()) + { + // At this point, we completed two different checks for whether it's a + // `callPackage`. + match (is_semantic_call_package, optional_syntactic_call_package.as_ref()) { + // Something like ` = { }` + (false, None) + // Something like ` = pythonPackages.callPackage ...` + | (false, Some(_)) + // Something like ` = bar` where `bar = pkgs.callPackage ...` + | (true, None) => NonApplicable, + // Something like ` = pkgs.callPackage ...` + (true, Some(syntactic_call_package)) => { + // It's only possible to migrate such definitions if.. + match syntactic_call_package.relative_path { + Some(ref rel_path) if rel_path.starts_with(BASE_SUBPATH) => { + // ..the path is not already within `pkgs/by-name` like + // + // foo-variant = callPackage ../by-name/fo/foo/package.nix { + // someFlag = true; + // } + // + // While such definitions could be moved to `pkgs/by-name` by + // using `.override { someFlag = true; }` instead, this changes + // the semantics in relation with overlays, so migration is + // generally not possible. + // + // See also "package variants" in RFC 140: + // https://github.com/NixOS/rfcs/blob/master/rfcs/0140-simple-package-paths.md#package-variants + NonApplicable + } + _ => Loose((syntactic_call_package.clone(), location.file.clone())), + } + } + } + } else { NonApplicable - } + }; - // Something like ` = pkgs.callPackage ...` - (true, Some(syntactic_call_package)) => { - // It's only possible to migrate such a definitions if.. - match syntactic_call_package.relative_path { - Some(ref rel_path) if rel_path.starts_with(BASE_SUBPATH) => { - // ..the path is not already within `pkgs/by-name` like - // - // foo-variant = callPackage ../by-name/fo/foo/package.nix { - // someFlag = true; - // } - // - // While such definitions could be moved to `pkgs/by-name` by using - // `.override { someFlag = true; }` instead, this changes the semantics in - // relation with overlays, so migration is generally not possible. - // - // See also "package variants" in RFC 140: - // https://github.com/NixOS/rfcs/blob/master/rfcs/0140-simple-package-paths.md#package-variants - NonApplicable - } - _ => { - // Otherwise, the path is outside `pkgs/by-name`, which means it can be - // migrated. - Loose((syntactic_call_package, location.file)) - } - } + ratchet::Package { + // Packages being checked in this function _always_ need a manual definition, + // because they're not using `pkgs/by-name` which would allow avoiding it. So the + // ratchet stays `Tight` regardless of the other checks in this function. + manual_definition: Tight, + uses_by_name, } } - } else { - // This catches all the cases not matched by the above `if let`, falling back to not being - // able to migrate such attributes. - NonApplicable + // This catches all the cases not matched by the above `EvalSuccess`, falling back to not + // being able to make any good calls about the ratchet state. + _ => ratchet::Package { + manual_definition: Tight, + uses_by_name: NonApplicable, + }, }; - Ok(Success(ratchet::Package { - // Packages being checked in this function _always_ need a manual definition, because - // they're not using `pkgs/by-name` which would allow avoiding it. So instead of repeating - // ourselves all the time to define `manual_definition`, just set it once at the end here. - manual_definition: Tight, - uses_by_name, - })) + Ok(Success(package)) } diff --git a/src/nix_file.rs b/src/nix_file.rs index 42bcd06c..dfae403f 100644 --- a/src/nix_file.rs +++ b/src/nix_file.rs @@ -78,7 +78,7 @@ impl NixFile { } /// Information about `callPackage` arguments. -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct CallPackageArgumentInfo { /// The relative path of the first argument, or `None` if it's not a path. pub relative_path: Option, From 7882ba6907ecdb05b5180f7e8a4e0285b760742d Mon Sep 17 00:00:00 2001 From: Tobias Mayer Date: Sun, 8 Mar 2026 11:26:51 +0100 Subject: [PATCH 3/4] Add __structuredAttrs ratchet and tests Co-authored-by: Michael Daniels --- README.md | 2 + src/eval.nix | 1 + src/eval.rs | 52 +++++++++++++++---- src/problem/mod.rs | 14 +++++ src/problem/npv_166.rs | 26 ++++++++++ src/problem/npv_167.rs | 26 ++++++++++ src/ratchet.rs | 29 ++++++++++- tests/mock-nixpkgs.nix | 1 + tests/structured-attrs-new-false/expected | 4 ++ .../main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + tests/structured-attrs-new-true/expected | 1 + .../main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + tests/structured-attrs-new-unset/expected | 4 ++ .../main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + .../base/default.nix | 1 + .../base/pkgs/by-name/README.md | 1 + .../base/pkgs/by-name/fo/foo/package.nix | 1 + tests/structured-attrs-regression/expected | 4 ++ .../main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + 27 files changed, 168 insertions(+), 11 deletions(-) create mode 100644 src/problem/npv_166.rs create mode 100644 src/problem/npv_167.rs create mode 100644 tests/structured-attrs-new-false/expected create mode 100644 tests/structured-attrs-new-false/main/default.nix create mode 100644 tests/structured-attrs-new-false/main/pkgs/by-name/README.md create mode 100644 tests/structured-attrs-new-false/main/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/structured-attrs-new-true/expected create mode 100644 tests/structured-attrs-new-true/main/default.nix create mode 100644 tests/structured-attrs-new-true/main/pkgs/by-name/README.md create mode 100644 tests/structured-attrs-new-true/main/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/structured-attrs-new-unset/expected create mode 100644 tests/structured-attrs-new-unset/main/default.nix create mode 100644 tests/structured-attrs-new-unset/main/pkgs/by-name/README.md create mode 100644 tests/structured-attrs-new-unset/main/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/structured-attrs-regression/base/default.nix create mode 100644 tests/structured-attrs-regression/base/pkgs/by-name/README.md create mode 100644 tests/structured-attrs-regression/base/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/structured-attrs-regression/expected create mode 100644 tests/structured-attrs-regression/main/default.nix create mode 100644 tests/structured-attrs-regression/main/pkgs/by-name/README.md create mode 100644 tests/structured-attrs-regression/main/pkgs/by-name/fo/foo/package.nix diff --git a/README.md b/README.md index 90af2300..7eacf8a6 100644 --- a/README.md +++ b/README.md @@ -96,3 +96,5 @@ The current ratchets are: (see [nix evaluation checks](#nix-evaluation-checks)) must not be introduced. - New top-level packages defined using `pkgs.callPackage` must be defined with a package directory. - Once a top-level package uses `pkgs/by-name`, it also can't be moved back out of it. +- New top-level packages must evaluate with `__structuredAttrs = true`. + - Once a top-level package evaluates with `__structuredAttrs = true`, it also can't regress to `false`. diff --git a/src/eval.nix b/src/eval.nix index f3c6f5d8..523d747c 100644 --- a/src/eval.nix +++ b/src/eval.nix @@ -60,6 +60,7 @@ let { AttributeSet = { is_derivation = pkgs.lib.isDerivation value; + structured_attrs = value.__structuredAttrs or false; definition_variant = if !value ? _callPackageVariant then { ManualDefinition.is_semantic_call_package = false; } diff --git a/src/eval.rs b/src/eval.rs index 9739304c..bd5da6cf 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -81,6 +81,8 @@ pub enum AttributeVariant { AttributeSet { /// Whether the attribute is a derivation (`lib.isDerivation`) is_derivation: bool, + /// Whether the attribute evaluates with `__structuredAttrs = true`. + structured_attrs: bool, /// The type of `callPackage` used. definition_variant: DefinitionVariant, }, @@ -298,6 +300,7 @@ fn by_name( attribute_variant: AttributeVariant::AttributeSet { is_derivation, + structured_attrs, definition_variant, }, location, @@ -373,18 +376,26 @@ fn by_name( // Independently report problems about whether it's a derivation and the callPackage // variant. - is_derivation_result.and_(variant_result) + is_derivation_result + .and_(variant_result) + .map(|manual_definition| ratchet::Package { + manual_definition, + uses_by_name: Tight, + structured_attrs: enabled_attribute_ratchet( + structured_attrs, + structure::relative_file_for_package(attribute_name), + ), + }) } }; - Ok( - // Packages being checked in this function are _always_ already defined in `pkgs/by-name`, - // so instead of repeating ourselves all the time to define `uses_by_name`, just set it - // once at the end with a map. - manual_definition_result.map(|manual_definition| ratchet::Package { - manual_definition, - uses_by_name: Tight, - }), - ) + Ok(manual_definition_result) +} + +fn enabled_attribute_ratchet(enabled: bool, file: RelativePathBuf) -> ratchet::RatchetState +where + R: ratchet::ToProblem, +{ + if enabled { Tight } else { Loose(file) } } /// Handles the case for packages in `pkgs/by-name` that are manually overridden, @@ -480,6 +491,7 @@ fn handle_non_by_name_attribute( AttributeVariant::AttributeSet { // As of today, non-derivation attribute sets can't be in `pkgs/by-name`. is_derivation: true, + structured_attrs, // Of the two definition variants, really only the manual one makes sense // here. // @@ -573,12 +585,31 @@ fn handle_non_by_name_attribute( NonApplicable }; + // For evaluated boolean ratchets, point at the package file when we can resolve one. + // Otherwise fall back to the file that defines the top-level attribute. + let evaluated_attribute_file = + parsed_definition + .as_ref() + .map(|(location, optional_syntactic_call_package)| { + optional_syntactic_call_package + .as_ref() + .and_then(|call_package| call_package.relative_path.clone()) + .unwrap_or_else(|| location.file.clone()) + }); + + let structured_attrs = match (structured_attrs, evaluated_attribute_file) { + (true, _) => Tight, + (false, Some(file)) => Loose(file), + (false, None) => NonApplicable, + }; + ratchet::Package { // Packages being checked in this function _always_ need a manual definition, // because they're not using `pkgs/by-name` which would allow avoiding it. So the // ratchet stays `Tight` regardless of the other checks in this function. manual_definition: Tight, uses_by_name, + structured_attrs, } } // This catches all the cases not matched by the above `EvalSuccess`, falling back to not @@ -586,6 +617,7 @@ fn handle_non_by_name_attribute( _ => ratchet::Package { manual_definition: Tight, uses_by_name: NonApplicable, + structured_attrs: NonApplicable, }, }; Ok(Success(package)) diff --git a/src/problem/mod.rs b/src/problem/mod.rs index 95e22f32..5c3db94e 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -36,6 +36,8 @@ pub mod npv_160; pub mod npv_161; pub mod npv_162; pub mod npv_163; +pub mod npv_166; +pub mod npv_167; const WIKI_BASE_URL: &str = "https://github.com/NixOS/nixpkgs-vet/wiki"; @@ -134,6 +136,14 @@ pub enum Problem { NewTopLevelPackageShouldBeByNameWithCustomArgument( npv_163::NewTopLevelPackageShouldBeByNameWithCustomArgument, ), + + /// NPV-166: new top-level package must enable __structuredAttrs + NewTopLevelPackageMustEnableStructuredAttrs( + npv_166::NewTopLevelPackageMustEnableStructuredAttrs, + ), + + /// NPV-167: top-level package disabled __structuredAttrs + TopLevelPackageDisabledStructuredAttrs(npv_167::TopLevelPackageDisabledStructuredAttrs), } impl Problem { @@ -170,6 +180,8 @@ impl Problem { Self::TopLevelPackageMovedOutOfByNameWithCustomArguments(..) => "NPV-161", Self::NewTopLevelPackageShouldBeByName(..) => "NPV-162", Self::NewTopLevelPackageShouldBeByNameWithCustomArgument(..) => "NPV-163", + Self::NewTopLevelPackageMustEnableStructuredAttrs(..) => "NPV-166", + Self::TopLevelPackageDisabledStructuredAttrs(..) => "NPV-167", } } @@ -212,6 +224,8 @@ impl fmt::Display for Problem { Self::TopLevelPackageMovedOutOfByNameWithCustomArguments(inner) => inner.fmt(f), Self::NewTopLevelPackageShouldBeByName(inner) => inner.fmt(f), Self::NewTopLevelPackageShouldBeByNameWithCustomArgument(inner) => inner.fmt(f), + Self::NewTopLevelPackageMustEnableStructuredAttrs(inner) => inner.fmt(f), + Self::TopLevelPackageDisabledStructuredAttrs(inner) => inner.fmt(f), } } } diff --git a/src/problem/npv_166.rs b/src/problem/npv_166.rs new file mode 100644 index 00000000..2e003037 --- /dev/null +++ b/src/problem/npv_166.rs @@ -0,0 +1,26 @@ +use std::fmt; + +use derive_new::new; +use indoc::writedoc; +use relative_path::RelativePathBuf; + +#[derive(Clone, new)] +pub struct NewTopLevelPackageMustEnableStructuredAttrs { + #[new(into)] + package_name: String, + #[new(into)] + file: RelativePathBuf, +} + +impl fmt::Display for NewTopLevelPackageMustEnableStructuredAttrs { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Self { package_name, file } = self; + writedoc!( + f, + " + - Attribute `pkgs.{package_name}` is a new package with `__structuredAttrs` unset or set to `false`. + Please enable `__structuredAttrs = true;` in {file}. + ", + ) + } +} diff --git a/src/problem/npv_167.rs b/src/problem/npv_167.rs new file mode 100644 index 00000000..9c490448 --- /dev/null +++ b/src/problem/npv_167.rs @@ -0,0 +1,26 @@ +use std::fmt; + +use derive_new::new; +use indoc::writedoc; +use relative_path::RelativePathBuf; + +#[derive(Clone, new)] +pub struct TopLevelPackageDisabledStructuredAttrs { + #[new(into)] + package_name: String, + #[new(into)] + file: RelativePathBuf, +} + +impl fmt::Display for TopLevelPackageDisabledStructuredAttrs { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Self { package_name, file } = self; + writedoc!( + f, + " + - Attribute `pkgs.{package_name}` previously evaluated with `__structuredAttrs = true`, but now evaluates with `__structuredAttrs = false`. + Please re-enable `__structuredAttrs = true;` in {file}. + ", + ) + } +} diff --git a/src/ratchet.rs b/src/ratchet.rs index 99c07ee7..3ef950aa 100644 --- a/src/ratchet.rs +++ b/src/ratchet.rs @@ -10,7 +10,7 @@ use std::collections::BTreeMap; use relative_path::RelativePathBuf; use crate::nix_file::CallPackageArgumentInfo; -use crate::problem::{Problem, npv_160, npv_161, npv_162, npv_163}; +use crate::problem::{Problem, npv_160, npv_161, npv_162, npv_163, npv_166, npv_167}; use crate::validation::{self, Validation, Validation::Success}; /// The ratchet value for the entirety of Nixpkgs. @@ -44,6 +44,9 @@ pub struct Package { /// The ratchet value for the check for new packages using pkgs/by-name pub uses_by_name: RatchetState, + + /// The ratchet value for the check for enabling `__structuredAttrs`. + pub structured_attrs: RatchetState, } impl Package { @@ -60,6 +63,11 @@ impl Package { optional_from.map(|x| &x.uses_by_name), &to.uses_by_name, ), + RatchetState::::compare( + name, + optional_from.map(|x| &x.structured_attrs), + &to.structured_attrs, + ), ]) } } @@ -214,3 +222,22 @@ impl ToProblem for EnabledAttribute; + +pub enum StructuredAttrsProblem {} + +impl EnabledAttributeProblem for StructuredAttrsProblem { + fn introduced_problem(name: &str, file: RelativePathBuf) -> Problem { + npv_166::NewTopLevelPackageMustEnableStructuredAttrs::new(name, file).into() + } + + fn regressed_problem(name: &str, file: RelativePathBuf) -> Problem { + npv_167::TopLevelPackageDisabledStructuredAttrs::new(name, file).into() + } +} diff --git a/tests/mock-nixpkgs.nix b/tests/mock-nixpkgs.nix index 5ba41879..b0a43cb9 100644 --- a/tests/mock-nixpkgs.nix +++ b/tests/mock-nixpkgs.nix @@ -43,6 +43,7 @@ let // lib.mapAttrs (name: value: value) { someDrv = { type = "derivation"; + __structuredAttrs = true; }; }; diff --git a/tests/structured-attrs-new-false/expected b/tests/structured-attrs-new-false/expected new file mode 100644 index 00000000..05a33c7b --- /dev/null +++ b/tests/structured-attrs-new-false/expected @@ -0,0 +1,4 @@ +- Attribute `pkgs.foo` is a new package with `__structuredAttrs` unset or set to `false`. + Please enable `__structuredAttrs = true;` in pkgs/by-name/fo/foo/package.nix. + (https://github.com/NixOS/nixpkgs-vet/wiki/NPV-166) +This PR introduces additional instances of discouraged patterns as listed above. Please fix them before merging. diff --git a/tests/structured-attrs-new-false/main/default.nix b/tests/structured-attrs-new-false/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/structured-attrs-new-false/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/structured-attrs-new-false/main/pkgs/by-name/README.md b/tests/structured-attrs-new-false/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/structured-attrs-new-false/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/structured-attrs-new-false/main/pkgs/by-name/fo/foo/package.nix b/tests/structured-attrs-new-false/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..4439b6c3 --- /dev/null +++ b/tests/structured-attrs-new-false/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv // { __structuredAttrs = false; } diff --git a/tests/structured-attrs-new-true/expected b/tests/structured-attrs-new-true/expected new file mode 100644 index 00000000..defae263 --- /dev/null +++ b/tests/structured-attrs-new-true/expected @@ -0,0 +1 @@ +Validated successfully diff --git a/tests/structured-attrs-new-true/main/default.nix b/tests/structured-attrs-new-true/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/structured-attrs-new-true/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/structured-attrs-new-true/main/pkgs/by-name/README.md b/tests/structured-attrs-new-true/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/structured-attrs-new-true/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/structured-attrs-new-true/main/pkgs/by-name/fo/foo/package.nix b/tests/structured-attrs-new-true/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..c0b68f99 --- /dev/null +++ b/tests/structured-attrs-new-true/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv // { __structuredAttrs = true; } diff --git a/tests/structured-attrs-new-unset/expected b/tests/structured-attrs-new-unset/expected new file mode 100644 index 00000000..05a33c7b --- /dev/null +++ b/tests/structured-attrs-new-unset/expected @@ -0,0 +1,4 @@ +- Attribute `pkgs.foo` is a new package with `__structuredAttrs` unset or set to `false`. + Please enable `__structuredAttrs = true;` in pkgs/by-name/fo/foo/package.nix. + (https://github.com/NixOS/nixpkgs-vet/wiki/NPV-166) +This PR introduces additional instances of discouraged patterns as listed above. Please fix them before merging. diff --git a/tests/structured-attrs-new-unset/main/default.nix b/tests/structured-attrs-new-unset/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/structured-attrs-new-unset/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/structured-attrs-new-unset/main/pkgs/by-name/README.md b/tests/structured-attrs-new-unset/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/structured-attrs-new-unset/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/structured-attrs-new-unset/main/pkgs/by-name/fo/foo/package.nix b/tests/structured-attrs-new-unset/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..3b184b77 --- /dev/null +++ b/tests/structured-attrs-new-unset/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: removeAttrs someDrv [ "__structuredAttrs" ] diff --git a/tests/structured-attrs-regression/base/default.nix b/tests/structured-attrs-regression/base/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/structured-attrs-regression/base/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/structured-attrs-regression/base/pkgs/by-name/README.md b/tests/structured-attrs-regression/base/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/structured-attrs-regression/base/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/structured-attrs-regression/base/pkgs/by-name/fo/foo/package.nix b/tests/structured-attrs-regression/base/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..a1b92efb --- /dev/null +++ b/tests/structured-attrs-regression/base/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv diff --git a/tests/structured-attrs-regression/expected b/tests/structured-attrs-regression/expected new file mode 100644 index 00000000..627e2165 --- /dev/null +++ b/tests/structured-attrs-regression/expected @@ -0,0 +1,4 @@ +- Attribute `pkgs.foo` previously evaluated with `__structuredAttrs = true`, but now evaluates with `__structuredAttrs = false`. + Please re-enable `__structuredAttrs = true;` in pkgs/by-name/fo/foo/package.nix. + (https://github.com/NixOS/nixpkgs-vet/wiki/NPV-167) +This PR introduces additional instances of discouraged patterns as listed above. Please fix them before merging. diff --git a/tests/structured-attrs-regression/main/default.nix b/tests/structured-attrs-regression/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/structured-attrs-regression/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/structured-attrs-regression/main/pkgs/by-name/README.md b/tests/structured-attrs-regression/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/structured-attrs-regression/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/structured-attrs-regression/main/pkgs/by-name/fo/foo/package.nix b/tests/structured-attrs-regression/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..4439b6c3 --- /dev/null +++ b/tests/structured-attrs-regression/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv // { __structuredAttrs = false; } From 4d45bcae724a16dd3907cb27a639dac2d9874878 Mon Sep 17 00:00:00 2001 From: Tobias Mayer Date: Sun, 8 Mar 2026 11:02:57 +0100 Subject: [PATCH 4/4] Add strictDeps ratchet and tests Co-authored-by: Michael Daniels --- README.md | 2 ++ src/eval.nix | 1 + src/eval.rs | 16 ++++++++++ src/problem/mod.rs | 12 ++++++++ src/problem/npv_164.rs | 26 ++++++++++++++++ src/problem/npv_165.rs | 26 ++++++++++++++++ src/ratchet.rs | 30 ++++++++++++++++++- tests/mock-nixpkgs.nix | 1 + tests/strict-deps-new-false/expected | 4 +++ tests/strict-deps-new-false/main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + tests/strict-deps-new-true/expected | 1 + tests/strict-deps-new-true/main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + tests/strict-deps-new-unset/expected | 4 +++ tests/strict-deps-new-unset/main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + tests/strict-deps-regression/base/default.nix | 1 + .../base/pkgs/by-name/README.md | 1 + .../base/pkgs/by-name/fo/foo/package.nix | 1 + tests/strict-deps-regression/expected | 4 +++ tests/strict-deps-regression/main/default.nix | 1 + .../main/pkgs/by-name/README.md | 1 + .../main/pkgs/by-name/fo/foo/package.nix | 1 + 27 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/problem/npv_164.rs create mode 100644 src/problem/npv_165.rs create mode 100644 tests/strict-deps-new-false/expected create mode 100644 tests/strict-deps-new-false/main/default.nix create mode 100644 tests/strict-deps-new-false/main/pkgs/by-name/README.md create mode 100644 tests/strict-deps-new-false/main/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/strict-deps-new-true/expected create mode 100644 tests/strict-deps-new-true/main/default.nix create mode 100644 tests/strict-deps-new-true/main/pkgs/by-name/README.md create mode 100644 tests/strict-deps-new-true/main/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/strict-deps-new-unset/expected create mode 100644 tests/strict-deps-new-unset/main/default.nix create mode 100644 tests/strict-deps-new-unset/main/pkgs/by-name/README.md create mode 100644 tests/strict-deps-new-unset/main/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/strict-deps-regression/base/default.nix create mode 100644 tests/strict-deps-regression/base/pkgs/by-name/README.md create mode 100644 tests/strict-deps-regression/base/pkgs/by-name/fo/foo/package.nix create mode 100644 tests/strict-deps-regression/expected create mode 100644 tests/strict-deps-regression/main/default.nix create mode 100644 tests/strict-deps-regression/main/pkgs/by-name/README.md create mode 100644 tests/strict-deps-regression/main/pkgs/by-name/fo/foo/package.nix diff --git a/README.md b/README.md index 7eacf8a6..31f5d0e9 100644 --- a/README.md +++ b/README.md @@ -96,5 +96,7 @@ The current ratchets are: (see [nix evaluation checks](#nix-evaluation-checks)) must not be introduced. - New top-level packages defined using `pkgs.callPackage` must be defined with a package directory. - Once a top-level package uses `pkgs/by-name`, it also can't be moved back out of it. +- New top-level packages must evaluate with `strictDeps = true`. + - Once a top-level package evaluates with `strictDeps = true`, it also can't regress to `false`. - New top-level packages must evaluate with `__structuredAttrs = true`. - Once a top-level package evaluates with `__structuredAttrs = true`, it also can't regress to `false`. diff --git a/src/eval.nix b/src/eval.nix index 523d747c..01517887 100644 --- a/src/eval.nix +++ b/src/eval.nix @@ -60,6 +60,7 @@ let { AttributeSet = { is_derivation = pkgs.lib.isDerivation value; + strict_deps = value.strictDeps or false; structured_attrs = value.__structuredAttrs or false; definition_variant = if !value ? _callPackageVariant then diff --git a/src/eval.rs b/src/eval.rs index bd5da6cf..a30856b7 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -81,6 +81,8 @@ pub enum AttributeVariant { AttributeSet { /// Whether the attribute is a derivation (`lib.isDerivation`) is_derivation: bool, + /// Whether the attribute evaluates with `strictDeps = true`. + strict_deps: bool, /// Whether the attribute evaluates with `__structuredAttrs = true`. structured_attrs: bool, /// The type of `callPackage` used. @@ -300,6 +302,7 @@ fn by_name( attribute_variant: AttributeVariant::AttributeSet { is_derivation, + strict_deps, structured_attrs, definition_variant, }, @@ -381,6 +384,10 @@ fn by_name( .map(|manual_definition| ratchet::Package { manual_definition, uses_by_name: Tight, + strict_deps: enabled_attribute_ratchet( + strict_deps, + structure::relative_file_for_package(attribute_name), + ), structured_attrs: enabled_attribute_ratchet( structured_attrs, structure::relative_file_for_package(attribute_name), @@ -491,6 +498,7 @@ fn handle_non_by_name_attribute( AttributeVariant::AttributeSet { // As of today, non-derivation attribute sets can't be in `pkgs/by-name`. is_derivation: true, + strict_deps, structured_attrs, // Of the two definition variants, really only the manual one makes sense // here. @@ -597,6 +605,12 @@ fn handle_non_by_name_attribute( .unwrap_or_else(|| location.file.clone()) }); + let strict_deps = match (strict_deps, evaluated_attribute_file.clone()) { + (true, _) => Tight, + (false, Some(file)) => Loose(file), + (false, None) => NonApplicable, + }; + let structured_attrs = match (structured_attrs, evaluated_attribute_file) { (true, _) => Tight, (false, Some(file)) => Loose(file), @@ -609,6 +623,7 @@ fn handle_non_by_name_attribute( // ratchet stays `Tight` regardless of the other checks in this function. manual_definition: Tight, uses_by_name, + strict_deps, structured_attrs, } } @@ -617,6 +632,7 @@ fn handle_non_by_name_attribute( _ => ratchet::Package { manual_definition: Tight, uses_by_name: NonApplicable, + strict_deps: NonApplicable, structured_attrs: NonApplicable, }, }; diff --git a/src/problem/mod.rs b/src/problem/mod.rs index 5c3db94e..e29950db 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -36,6 +36,8 @@ pub mod npv_160; pub mod npv_161; pub mod npv_162; pub mod npv_163; +pub mod npv_164; +pub mod npv_165; pub mod npv_166; pub mod npv_167; @@ -137,6 +139,12 @@ pub enum Problem { npv_163::NewTopLevelPackageShouldBeByNameWithCustomArgument, ), + /// NPV-164: new top-level package must enable strictDeps + NewTopLevelPackageMustEnableStrictDeps(npv_164::NewTopLevelPackageMustEnableStrictDeps), + + /// NPV-165: top-level package disabled strictDeps + TopLevelPackageDisabledStrictDeps(npv_165::TopLevelPackageDisabledStrictDeps), + /// NPV-166: new top-level package must enable __structuredAttrs NewTopLevelPackageMustEnableStructuredAttrs( npv_166::NewTopLevelPackageMustEnableStructuredAttrs, @@ -180,6 +188,8 @@ impl Problem { Self::TopLevelPackageMovedOutOfByNameWithCustomArguments(..) => "NPV-161", Self::NewTopLevelPackageShouldBeByName(..) => "NPV-162", Self::NewTopLevelPackageShouldBeByNameWithCustomArgument(..) => "NPV-163", + Self::NewTopLevelPackageMustEnableStrictDeps(..) => "NPV-164", + Self::TopLevelPackageDisabledStrictDeps(..) => "NPV-165", Self::NewTopLevelPackageMustEnableStructuredAttrs(..) => "NPV-166", Self::TopLevelPackageDisabledStructuredAttrs(..) => "NPV-167", } @@ -224,6 +234,8 @@ impl fmt::Display for Problem { Self::TopLevelPackageMovedOutOfByNameWithCustomArguments(inner) => inner.fmt(f), Self::NewTopLevelPackageShouldBeByName(inner) => inner.fmt(f), Self::NewTopLevelPackageShouldBeByNameWithCustomArgument(inner) => inner.fmt(f), + Self::NewTopLevelPackageMustEnableStrictDeps(inner) => inner.fmt(f), + Self::TopLevelPackageDisabledStrictDeps(inner) => inner.fmt(f), Self::NewTopLevelPackageMustEnableStructuredAttrs(inner) => inner.fmt(f), Self::TopLevelPackageDisabledStructuredAttrs(inner) => inner.fmt(f), } diff --git a/src/problem/npv_164.rs b/src/problem/npv_164.rs new file mode 100644 index 00000000..e9feecde --- /dev/null +++ b/src/problem/npv_164.rs @@ -0,0 +1,26 @@ +use std::fmt; + +use derive_new::new; +use indoc::writedoc; +use relative_path::RelativePathBuf; + +#[derive(Clone, new)] +pub struct NewTopLevelPackageMustEnableStrictDeps { + #[new(into)] + package_name: String, + #[new(into)] + file: RelativePathBuf, +} + +impl fmt::Display for NewTopLevelPackageMustEnableStrictDeps { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Self { package_name, file } = self; + writedoc!( + f, + " + - Attribute `pkgs.{package_name}` is a new package with `strictDeps` unset or set to `false`. + Please enable `strictDeps = true;` in {file}. + ", + ) + } +} diff --git a/src/problem/npv_165.rs b/src/problem/npv_165.rs new file mode 100644 index 00000000..a9b5e3eb --- /dev/null +++ b/src/problem/npv_165.rs @@ -0,0 +1,26 @@ +use std::fmt; + +use derive_new::new; +use indoc::writedoc; +use relative_path::RelativePathBuf; + +#[derive(Clone, new)] +pub struct TopLevelPackageDisabledStrictDeps { + #[new(into)] + package_name: String, + #[new(into)] + file: RelativePathBuf, +} + +impl fmt::Display for TopLevelPackageDisabledStrictDeps { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Self { package_name, file } = self; + writedoc!( + f, + " + - Attribute `pkgs.{package_name}` previously evaluated with `strictDeps = true`, but now evaluates with `strictDeps = false`. + Please re-enable `strictDeps = true;` in {file}. + ", + ) + } +} diff --git a/src/ratchet.rs b/src/ratchet.rs index 3ef950aa..835485d5 100644 --- a/src/ratchet.rs +++ b/src/ratchet.rs @@ -10,7 +10,9 @@ use std::collections::BTreeMap; use relative_path::RelativePathBuf; use crate::nix_file::CallPackageArgumentInfo; -use crate::problem::{Problem, npv_160, npv_161, npv_162, npv_163, npv_166, npv_167}; +use crate::problem::{ + Problem, npv_160, npv_161, npv_162, npv_163, npv_164, npv_165, npv_166, npv_167, +}; use crate::validation::{self, Validation, Validation::Success}; /// The ratchet value for the entirety of Nixpkgs. @@ -45,6 +47,9 @@ pub struct Package { /// The ratchet value for the check for new packages using pkgs/by-name pub uses_by_name: RatchetState, + /// The ratchet value for the check for enabling `strictDeps`. + pub strict_deps: RatchetState, + /// The ratchet value for the check for enabling `__structuredAttrs`. pub structured_attrs: RatchetState, } @@ -63,6 +68,11 @@ impl Package { optional_from.map(|x| &x.uses_by_name), &to.uses_by_name, ), + RatchetState::::compare( + name, + optional_from.map(|x| &x.strict_deps), + &to.strict_deps, + ), RatchetState::::compare( name, optional_from.map(|x| &x.structured_attrs), @@ -223,6 +233,24 @@ impl ToProblem for EnabledAttribute; + +pub enum StrictDepsProblem {} + +impl EnabledAttributeProblem for StrictDepsProblem { + fn introduced_problem(name: &str, file: RelativePathBuf) -> Problem { + npv_164::NewTopLevelPackageMustEnableStrictDeps::new(name, file).into() + } + + fn regressed_problem(name: &str, file: RelativePathBuf) -> Problem { + npv_165::TopLevelPackageDisabledStrictDeps::new(name, file).into() + } +} + /// The ratchet value of an attribute for enabling `__structuredAttrs`. /// /// New packages must evaluate with `__structuredAttrs = true` unless their package set already diff --git a/tests/mock-nixpkgs.nix b/tests/mock-nixpkgs.nix index b0a43cb9..35f246fe 100644 --- a/tests/mock-nixpkgs.nix +++ b/tests/mock-nixpkgs.nix @@ -43,6 +43,7 @@ let // lib.mapAttrs (name: value: value) { someDrv = { type = "derivation"; + strictDeps = true; __structuredAttrs = true; }; }; diff --git a/tests/strict-deps-new-false/expected b/tests/strict-deps-new-false/expected new file mode 100644 index 00000000..1ddf6c2b --- /dev/null +++ b/tests/strict-deps-new-false/expected @@ -0,0 +1,4 @@ +- Attribute `pkgs.foo` is a new package with `strictDeps` unset or set to `false`. + Please enable `strictDeps = true;` in pkgs/by-name/fo/foo/package.nix. + (https://github.com/NixOS/nixpkgs-vet/wiki/NPV-164) +This PR introduces additional instances of discouraged patterns as listed above. Please fix them before merging. diff --git a/tests/strict-deps-new-false/main/default.nix b/tests/strict-deps-new-false/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/strict-deps-new-false/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/strict-deps-new-false/main/pkgs/by-name/README.md b/tests/strict-deps-new-false/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/strict-deps-new-false/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/strict-deps-new-false/main/pkgs/by-name/fo/foo/package.nix b/tests/strict-deps-new-false/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..e57d93e4 --- /dev/null +++ b/tests/strict-deps-new-false/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv // { strictDeps = false; } diff --git a/tests/strict-deps-new-true/expected b/tests/strict-deps-new-true/expected new file mode 100644 index 00000000..defae263 --- /dev/null +++ b/tests/strict-deps-new-true/expected @@ -0,0 +1 @@ +Validated successfully diff --git a/tests/strict-deps-new-true/main/default.nix b/tests/strict-deps-new-true/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/strict-deps-new-true/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/strict-deps-new-true/main/pkgs/by-name/README.md b/tests/strict-deps-new-true/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/strict-deps-new-true/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/strict-deps-new-true/main/pkgs/by-name/fo/foo/package.nix b/tests/strict-deps-new-true/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..62c3689e --- /dev/null +++ b/tests/strict-deps-new-true/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv // { strictDeps = true; } diff --git a/tests/strict-deps-new-unset/expected b/tests/strict-deps-new-unset/expected new file mode 100644 index 00000000..1ddf6c2b --- /dev/null +++ b/tests/strict-deps-new-unset/expected @@ -0,0 +1,4 @@ +- Attribute `pkgs.foo` is a new package with `strictDeps` unset or set to `false`. + Please enable `strictDeps = true;` in pkgs/by-name/fo/foo/package.nix. + (https://github.com/NixOS/nixpkgs-vet/wiki/NPV-164) +This PR introduces additional instances of discouraged patterns as listed above. Please fix them before merging. diff --git a/tests/strict-deps-new-unset/main/default.nix b/tests/strict-deps-new-unset/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/strict-deps-new-unset/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/strict-deps-new-unset/main/pkgs/by-name/README.md b/tests/strict-deps-new-unset/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/strict-deps-new-unset/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/strict-deps-new-unset/main/pkgs/by-name/fo/foo/package.nix b/tests/strict-deps-new-unset/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..40d48fbb --- /dev/null +++ b/tests/strict-deps-new-unset/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: removeAttrs someDrv [ "strictDeps" ] diff --git a/tests/strict-deps-regression/base/default.nix b/tests/strict-deps-regression/base/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/strict-deps-regression/base/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/strict-deps-regression/base/pkgs/by-name/README.md b/tests/strict-deps-regression/base/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/strict-deps-regression/base/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/strict-deps-regression/base/pkgs/by-name/fo/foo/package.nix b/tests/strict-deps-regression/base/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..a1b92efb --- /dev/null +++ b/tests/strict-deps-regression/base/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv diff --git a/tests/strict-deps-regression/expected b/tests/strict-deps-regression/expected new file mode 100644 index 00000000..6ea4b152 --- /dev/null +++ b/tests/strict-deps-regression/expected @@ -0,0 +1,4 @@ +- Attribute `pkgs.foo` previously evaluated with `strictDeps = true`, but now evaluates with `strictDeps = false`. + Please re-enable `strictDeps = true;` in pkgs/by-name/fo/foo/package.nix. + (https://github.com/NixOS/nixpkgs-vet/wiki/NPV-165) +This PR introduces additional instances of discouraged patterns as listed above. Please fix them before merging. diff --git a/tests/strict-deps-regression/main/default.nix b/tests/strict-deps-regression/main/default.nix new file mode 100644 index 00000000..861260cd --- /dev/null +++ b/tests/strict-deps-regression/main/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/strict-deps-regression/main/pkgs/by-name/README.md b/tests/strict-deps-regression/main/pkgs/by-name/README.md new file mode 100644 index 00000000..232fdecb --- /dev/null +++ b/tests/strict-deps-regression/main/pkgs/by-name/README.md @@ -0,0 +1 @@ +# Test fixture diff --git a/tests/strict-deps-regression/main/pkgs/by-name/fo/foo/package.nix b/tests/strict-deps-regression/main/pkgs/by-name/fo/foo/package.nix new file mode 100644 index 00000000..e57d93e4 --- /dev/null +++ b/tests/strict-deps-regression/main/pkgs/by-name/fo/foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: someDrv // { strictDeps = false; }