tests.nixpkgs-check-by-name: Re-usable ratchet logic
This makes the attribute ratchet check logic more re-usable, which will be used in a future commit. It also renames the ratchet states to something more intuitive
This commit is contained in:
parent
ba6faf428f
commit
2a8f469348
2 changed files with 55 additions and 22 deletions
|
@ -130,6 +130,7 @@ pub fn check_values(
|
||||||
let relative_package_file = structure::relative_file_for_package(&attribute_name);
|
let relative_package_file = structure::relative_file_for_package(&attribute_name);
|
||||||
let absolute_package_file = nixpkgs_path.join(&relative_package_file);
|
let absolute_package_file = nixpkgs_path.join(&relative_package_file);
|
||||||
|
|
||||||
|
use ratchet::RatchetState::*;
|
||||||
use AttributeInfo::*;
|
use AttributeInfo::*;
|
||||||
use ByNameAttribute::*;
|
use ByNameAttribute::*;
|
||||||
use CallPackageVariant::*;
|
use CallPackageVariant::*;
|
||||||
|
@ -166,7 +167,7 @@ pub fn check_values(
|
||||||
|
|
||||||
check_result.and(match &call_package_variant {
|
check_result.and(match &call_package_variant {
|
||||||
Auto => Success(ratchet::Package {
|
Auto => Success(ratchet::Package {
|
||||||
empty_non_auto_called: ratchet::EmptyNonAutoCalled::Valid,
|
empty_non_auto_called: Tight,
|
||||||
}),
|
}),
|
||||||
Manual { path, empty_arg } => {
|
Manual { path, empty_arg } => {
|
||||||
let correct_file = if let Some(call_package_path) = path {
|
let correct_file = if let Some(call_package_path) = path {
|
||||||
|
@ -179,9 +180,9 @@ pub fn check_values(
|
||||||
Success(ratchet::Package {
|
Success(ratchet::Package {
|
||||||
// Empty arguments for non-auto-called packages are not allowed anymore.
|
// Empty arguments for non-auto-called packages are not allowed anymore.
|
||||||
empty_non_auto_called: if *empty_arg {
|
empty_non_auto_called: if *empty_arg {
|
||||||
ratchet::EmptyNonAutoCalled::Invalid
|
Loose(ratchet::EmptyNonAutoCalled)
|
||||||
} else {
|
} else {
|
||||||
ratchet::EmptyNonAutoCalled::Valid
|
Tight
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -30,7 +30,7 @@ impl Nixpkgs {
|
||||||
/// The ratchet value for a single package in `pkgs/by-name`
|
/// The ratchet value for a single package in `pkgs/by-name`
|
||||||
pub struct Package {
|
pub struct Package {
|
||||||
/// The ratchet value for the check for non-auto-called empty arguments
|
/// The ratchet value for the check for non-auto-called empty arguments
|
||||||
pub empty_non_auto_called: EmptyNonAutoCalled,
|
pub empty_non_auto_called: RatchetState<EmptyNonAutoCalled>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
|
@ -44,29 +44,61 @@ impl Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The ratchet value of a single package in `pkgs/by-name`
|
/// The ratchet state of a generic ratchet check.
|
||||||
|
pub enum RatchetState<Context> {
|
||||||
|
/// The ratchet is loose, it can be tightened more.
|
||||||
|
/// In other words, this is the legacy state we're trying to move away from.
|
||||||
|
/// Introducing new instances is now allowed but previous instances will continue to be allowed.
|
||||||
|
/// The `Context` is context for error messages in case a new instance of this state is
|
||||||
|
/// introduced
|
||||||
|
Loose(Context),
|
||||||
|
/// The ratchet is tight, it can't be tightened any further.
|
||||||
|
/// This is either because we already use the latest state, or because the ratchet isn't
|
||||||
|
/// relevant.
|
||||||
|
Tight,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for a specific ratchet check for an attribute.
|
||||||
|
trait AttributeRatchet: Sized {
|
||||||
|
/// What error to produce in case the ratchet went in the wrong direction
|
||||||
|
fn to_error(name: &str, context: &Self, existed_before: bool) -> NixpkgsProblem;
|
||||||
|
|
||||||
|
/// Compare the previous ratchet state of an attribute to the new state.
|
||||||
|
/// The previous state may be `None` in case the attribute is new.
|
||||||
|
fn compare(
|
||||||
|
name: &str,
|
||||||
|
optional_from: Option<&RatchetState<Self>>,
|
||||||
|
to: &RatchetState<Self>,
|
||||||
|
) -> Validation<()> {
|
||||||
|
// If we don't have a previous state, enforce a tight ratchet
|
||||||
|
let from = optional_from.unwrap_or(&RatchetState::Tight);
|
||||||
|
match (from, to) {
|
||||||
|
// Always okay to keep it tight or tighten the ratchet
|
||||||
|
(_, RatchetState::Tight) => Success(()),
|
||||||
|
|
||||||
|
// Grandfathering policy for a loose ratchet
|
||||||
|
(RatchetState::Loose { .. }, RatchetState::Loose { .. }) => Success(()),
|
||||||
|
|
||||||
|
// Loosening a ratchet is now allowed
|
||||||
|
(RatchetState::Tight, RatchetState::Loose(context)) => {
|
||||||
|
Self::to_error(name, context, optional_from.is_some()).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The ratchet value of an attribute
|
||||||
/// for the non-auto-called empty argument check of a single.
|
/// for the non-auto-called empty argument check of a single.
|
||||||
///
|
///
|
||||||
/// This checks that packages defined in `pkgs/by-name` cannot be overridden
|
/// This checks that packages defined in `pkgs/by-name` cannot be overridden
|
||||||
/// with an empty second argument like `callPackage ... { }`.
|
/// with an empty second argument like `callPackage ... { }`.
|
||||||
#[derive(PartialEq, PartialOrd)]
|
pub struct EmptyNonAutoCalled;
|
||||||
pub enum EmptyNonAutoCalled {
|
|
||||||
Invalid,
|
|
||||||
Valid,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EmptyNonAutoCalled {
|
impl AttributeRatchet for EmptyNonAutoCalled {
|
||||||
/// Validates the non-auto-called empty argument ratchet check for a single package defined in `pkgs/by-name`
|
fn to_error(name: &str, _context: &Self, _existed_before: bool) -> NixpkgsProblem {
|
||||||
fn compare(name: &str, optional_from: Option<&Self>, to: &Self) -> Validation<()> {
|
|
||||||
let from = optional_from.unwrap_or(&Self::Valid);
|
|
||||||
if to >= from {
|
|
||||||
Success(())
|
|
||||||
} else {
|
|
||||||
NixpkgsProblem::WrongCallPackage {
|
NixpkgsProblem::WrongCallPackage {
|
||||||
relative_package_file: structure::relative_file_for_package(name),
|
relative_package_file: structure::relative_file_for_package(name),
|
||||||
package_name: name.to_owned(),
|
package_name: name.to_owned(),
|
||||||
}
|
}
|
||||||
.into()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue