From 8be41ace99f26479ba1d5a7a0c413e0885113158 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Mon, 23 Oct 2023 23:58:51 +0200 Subject: tests.nixpkgs-check-by-name: Separate file for all problems And introduce a function for some smaller indentation --- .../test/nixpkgs-check-by-name/src/check_result.rs | 239 ++------------------- pkgs/test/nixpkgs-check-by-name/src/eval.rs | 9 +- pkgs/test/nixpkgs-check-by-name/src/main.rs | 1 + .../nixpkgs-check-by-name/src/nixpkgs_problem.rs | 218 +++++++++++++++++++ pkgs/test/nixpkgs-check-by-name/src/references.rs | 17 +- pkgs/test/nixpkgs-check-by-name/src/structure.rs | 166 +++++++------- 6 files changed, 331 insertions(+), 319 deletions(-) create mode 100644 pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs (limited to 'pkgs/test') diff --git a/pkgs/test/nixpkgs-check-by-name/src/check_result.rs b/pkgs/test/nixpkgs-check-by-name/src/check_result.rs index db2377c7204b2..a6538d778b618 100644 --- a/pkgs/test/nixpkgs-check-by-name/src/check_result.rs +++ b/pkgs/test/nixpkgs-check-by-name/src/check_result.rs @@ -1,243 +1,21 @@ -use crate::utils::PACKAGE_NIX_FILENAME; +use crate::nixpkgs_problem::NixpkgsProblem; use itertools::concat; use itertools::{ Either, Either::{Left, Right}, Itertools, }; -use rnix::parser::ParseError; -use std::ffi::OsString; -use std::fmt; -use std::io; -use std::path::PathBuf; - -pub enum CheckProblem { - ShardNonDir { - relative_shard_path: PathBuf, - }, - InvalidShardName { - relative_shard_path: PathBuf, - shard_name: String, - }, - PackageNonDir { - relative_package_dir: PathBuf, - }, - CaseSensitiveDuplicate { - relative_shard_path: PathBuf, - first: OsString, - second: OsString, - }, - InvalidPackageName { - relative_package_dir: PathBuf, - package_name: String, - }, - IncorrectShard { - relative_package_dir: PathBuf, - correct_relative_package_dir: PathBuf, - }, - PackageNixNonExistent { - relative_package_dir: PathBuf, - }, - PackageNixDir { - relative_package_dir: PathBuf, - }, - UndefinedAttr { - relative_package_file: PathBuf, - package_name: String, - }, - WrongCallPackage { - relative_package_file: PathBuf, - package_name: String, - }, - NonDerivation { - relative_package_file: PathBuf, - package_name: String, - }, - OutsideSymlink { - relative_package_dir: PathBuf, - subpath: PathBuf, - }, - UnresolvableSymlink { - relative_package_dir: PathBuf, - subpath: PathBuf, - io_error: io::Error, - }, - CouldNotParseNix { - relative_package_dir: PathBuf, - subpath: PathBuf, - error: ParseError, - }, - PathInterpolation { - relative_package_dir: PathBuf, - subpath: PathBuf, - line: usize, - text: String, - }, - SearchPath { - relative_package_dir: PathBuf, - subpath: PathBuf, - line: usize, - text: String, - }, - OutsidePathReference { - relative_package_dir: PathBuf, - subpath: PathBuf, - line: usize, - text: String, - }, - UnresolvablePathReference { - relative_package_dir: PathBuf, - subpath: PathBuf, - line: usize, - text: String, - io_error: io::Error, - }, -} - -impl CheckProblem { - pub fn into_result(self) -> CheckResult { - Ok(Left(vec![self])) - } -} - -impl fmt::Display for CheckProblem { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - CheckProblem::ShardNonDir { relative_shard_path } => - write!( - f, - "{}: This is a file, but it should be a directory.", - relative_shard_path.display(), - ), - CheckProblem::InvalidShardName { relative_shard_path, shard_name } => - write!( - f, - "{}: Invalid directory name \"{shard_name}\", must be at most 2 ASCII characters consisting of a-z, 0-9, \"-\" or \"_\".", - relative_shard_path.display() - ), - CheckProblem::PackageNonDir { relative_package_dir } => - write!( - f, - "{}: This path is a file, but it should be a directory.", - relative_package_dir.display(), - ), - CheckProblem::CaseSensitiveDuplicate { relative_shard_path, first, second } => - write!( - f, - "{}: Duplicate case-sensitive package directories {first:?} and {second:?}.", - relative_shard_path.display(), - ), - CheckProblem::InvalidPackageName { relative_package_dir, package_name } => - write!( - f, - "{}: Invalid package directory name \"{package_name}\", must be ASCII characters consisting of a-z, A-Z, 0-9, \"-\" or \"_\".", - relative_package_dir.display(), - ), - CheckProblem::IncorrectShard { relative_package_dir, correct_relative_package_dir } => - write!( - f, - "{}: Incorrect directory location, should be {} instead.", - relative_package_dir.display(), - correct_relative_package_dir.display(), - ), - CheckProblem::PackageNixNonExistent { relative_package_dir } => - write!( - f, - "{}: Missing required \"{PACKAGE_NIX_FILENAME}\" file.", - relative_package_dir.display(), - ), - CheckProblem::PackageNixDir { relative_package_dir } => - write!( - f, - "{}: \"{PACKAGE_NIX_FILENAME}\" must be a file.", - relative_package_dir.display(), - ), - CheckProblem::UndefinedAttr { relative_package_file, package_name } => - write!( - f, - "pkgs.{package_name}: This attribute is not defined but it should be defined automatically as {}", - relative_package_file.display() - ), - CheckProblem::WrongCallPackage { relative_package_file, package_name } => - write!( - f, - "pkgs.{package_name}: This attribute is manually defined (most likely in pkgs/top-level/all-packages.nix), which is only allowed if the definition is of the form `pkgs.callPackage {} {{ ... }}` with a non-empty second argument.", - relative_package_file.display() - ), - CheckProblem::NonDerivation { relative_package_file, package_name } => - write!( - f, - "pkgs.{package_name}: This attribute defined by {} is not a derivation", - relative_package_file.display() - ), - CheckProblem::OutsideSymlink { relative_package_dir, subpath } => - write!( - f, - "{}: Path {} is a symlink pointing to a path outside the directory of that package.", - relative_package_dir.display(), - subpath.display(), - ), - CheckProblem::UnresolvableSymlink { relative_package_dir, subpath, io_error } => - write!( - f, - "{}: Path {} is a symlink which cannot be resolved: {io_error}.", - relative_package_dir.display(), - subpath.display(), - ), - CheckProblem::CouldNotParseNix { relative_package_dir, subpath, error } => - write!( - f, - "{}: File {} could not be parsed by rnix: {}", - relative_package_dir.display(), - subpath.display(), - error, - ), - CheckProblem::PathInterpolation { relative_package_dir, subpath, line, text } => - write!( - f, - "{}: File {} at line {line} contains the path expression \"{}\", which is not yet supported and may point outside the directory of that package.", - relative_package_dir.display(), - subpath.display(), - text - ), - CheckProblem::SearchPath { relative_package_dir, subpath, line, text } => - write!( - f, - "{}: File {} at line {line} contains the nix search path expression \"{}\" which may point outside the directory of that package.", - relative_package_dir.display(), - subpath.display(), - text - ), - CheckProblem::OutsidePathReference { relative_package_dir, subpath, line, text } => - write!( - f, - "{}: File {} at line {line} contains the path expression \"{}\" which may point outside the directory of that package.", - relative_package_dir.display(), - subpath.display(), - text, - ), - CheckProblem::UnresolvablePathReference { relative_package_dir, subpath, line, text, io_error } => - write!( - f, - "{}: File {} at line {line} contains the path expression \"{}\" which cannot be resolved: {io_error}.", - relative_package_dir.display(), - subpath.display(), - text, - ), - } - } -} /// A type alias representing the result of a check, either: /// - Err(anyhow::Error): A fatal failure, typically I/O errors. /// Such failures are not caused by the files in Nixpkgs. /// This hints at a bug in the code or a problem with the deployment. -/// - Ok(Left(Vec)): A non-fatal problem with the Nixpkgs files. +/// - Ok(Left(Vec)): A non-fatal problem with the Nixpkgs files. /// Further checks can be run even with this result type. /// Such problems can be fixed by changing the Nixpkgs files. /// - Ok(Right(A)): A successful (potentially intermediate) result with an arbitrary value. /// No fatal errors have occurred and no problems have been found with Nixpkgs. -pub type CheckResult = anyhow::Result, A>>; +pub type CheckResult = anyhow::Result, A>>; /// Map a `CheckResult` to a `CheckResult` by applying a function to the /// potentially contained value in case of success. @@ -250,8 +28,15 @@ pub fn ok(value: A) -> CheckResult { Ok(Right(value)) } +impl NixpkgsProblem { + /// Create a `CheckResult` from a single check problem + pub fn into_result(self) -> CheckResult { + Ok(Left(vec![self])) + } +} + /// Combine two check results, both of which need to be successful for the return value to be successful. -/// The `CheckProblem`s of both sides are returned concatenated. +/// The `NixpkgsProblem`s of both sides are returned concatenated. pub fn and(first: CheckResult<()>, second: CheckResult) -> CheckResult { match (first?, second?) { (Right(_), Right(right_value)) => Ok(Right(right_value)), @@ -264,7 +49,7 @@ pub fn and(first: CheckResult<()>, second: CheckResult) -> CheckResult /// Combine many checks results into a single one. /// All given check results need to be successful in order for the returned check result to be successful, /// in which case the returned check result value contains each a `Vec` of each individual result value. -/// The `CheckProblem`s of all results are returned concatenated. +/// The `NixpkgsProblem`s of all results are returned concatenated. pub fn sequence(check_results: impl IntoIterator>) -> CheckResult> { let (errors, values): (Vec<_>, Vec<_>) = check_results .into_iter() diff --git a/pkgs/test/nixpkgs-check-by-name/src/eval.rs b/pkgs/test/nixpkgs-check-by-name/src/eval.rs index a76abba05d964..37fc783f3d34b 100644 --- a/pkgs/test/nixpkgs-check-by-name/src/eval.rs +++ b/pkgs/test/nixpkgs-check-by-name/src/eval.rs @@ -1,5 +1,6 @@ use crate::check_result; -use crate::check_result::{CheckProblem, CheckResult}; +use crate::check_result::CheckResult; +use crate::nixpkgs_problem::NixpkgsProblem; use crate::structure; use crate::Version; use std::path::Path; @@ -137,13 +138,13 @@ pub fn check_values( }; if !valid { - CheckProblem::WrongCallPackage { + NixpkgsProblem::WrongCallPackage { relative_package_file: relative_package_file.clone(), package_name: package_name.clone(), } .into_result() } else if !attribute_info.is_derivation { - CheckProblem::NonDerivation { + NixpkgsProblem::NonDerivation { relative_package_file: relative_package_file.clone(), package_name: package_name.clone(), } @@ -152,7 +153,7 @@ pub fn check_values( check_result::ok(()) } } else { - CheckProblem::UndefinedAttr { + NixpkgsProblem::UndefinedAttr { relative_package_file: relative_package_file.clone(), package_name: package_name.clone(), } diff --git a/pkgs/test/nixpkgs-check-by-name/src/main.rs b/pkgs/test/nixpkgs-check-by-name/src/main.rs index 11fedde741309..1651624f3f40b 100644 --- a/pkgs/test/nixpkgs-check-by-name/src/main.rs +++ b/pkgs/test/nixpkgs-check-by-name/src/main.rs @@ -1,5 +1,6 @@ mod check_result; mod eval; +mod nixpkgs_problem; mod references; mod structure; mod utils; diff --git a/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs b/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs new file mode 100644 index 0000000000000..2344a8cc13253 --- /dev/null +++ b/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs @@ -0,0 +1,218 @@ +use crate::utils::PACKAGE_NIX_FILENAME; +use rnix::parser::ParseError; +use std::ffi::OsString; +use std::fmt; +use std::io; +use std::path::PathBuf; + +/// Any problem that can occur when checking Nixpkgs +pub enum NixpkgsProblem { + ShardNonDir { + relative_shard_path: PathBuf, + }, + InvalidShardName { + relative_shard_path: PathBuf, + shard_name: String, + }, + PackageNonDir { + relative_package_dir: PathBuf, + }, + CaseSensitiveDuplicate { + relative_shard_path: PathBuf, + first: OsString, + second: OsString, + }, + InvalidPackageName { + relative_package_dir: PathBuf, + package_name: String, + }, + IncorrectShard { + relative_package_dir: PathBuf, + correct_relative_package_dir: PathBuf, + }, + PackageNixNonExistent { + relative_package_dir: PathBuf, + }, + PackageNixDir { + relative_package_dir: PathBuf, + }, + UndefinedAttr { + relative_package_file: PathBuf, + package_name: String, + }, + WrongCallPackage { + relative_package_file: PathBuf, + package_name: String, + }, + NonDerivation { + relative_package_file: PathBuf, + package_name: String, + }, + OutsideSymlink { + relative_package_dir: PathBuf, + subpath: PathBuf, + }, + UnresolvableSymlink { + relative_package_dir: PathBuf, + subpath: PathBuf, + io_error: io::Error, + }, + CouldNotParseNix { + relative_package_dir: PathBuf, + subpath: PathBuf, + error: ParseError, + }, + PathInterpolation { + relative_package_dir: PathBuf, + subpath: PathBuf, + line: usize, + text: String, + }, + SearchPath { + relative_package_dir: PathBuf, + subpath: PathBuf, + line: usize, + text: String, + }, + OutsidePathReference { + relative_package_dir: PathBuf, + subpath: PathBuf, + line: usize, + text: String, + }, + UnresolvablePathReference { + relative_package_dir: PathBuf, + subpath: PathBuf, + line: usize, + text: String, + io_error: io::Error, + }, +} + +impl fmt::Display for NixpkgsProblem { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + NixpkgsProblem::ShardNonDir { relative_shard_path } => + write!( + f, + "{}: This is a file, but it should be a directory.", + relative_shard_path.display(), + ), + NixpkgsProblem::InvalidShardName { relative_shard_path, shard_name } => + write!( + f, + "{}: Invalid directory name \"{shard_name}\", must be at most 2 ASCII characters consisting of a-z, 0-9, \"-\" or \"_\".", + relative_shard_path.display() + ), + NixpkgsProblem::PackageNonDir { relative_package_dir } => + write!( + f, + "{}: This path is a file, but it should be a directory.", + relative_package_dir.display(), + ), + NixpkgsProblem::CaseSensitiveDuplicate { relative_shard_path, first, second } => + write!( + f, + "{}: Duplicate case-sensitive package directories {first:?} and {second:?}.", + relative_shard_path.display(), + ), + NixpkgsProblem::InvalidPackageName { relative_package_dir, package_name } => + write!( + f, + "{}: Invalid package directory name \"{package_name}\", must be ASCII characters consisting of a-z, A-Z, 0-9, \"-\" or \"_\".", + relative_package_dir.display(), + ), + NixpkgsProblem::IncorrectShard { relative_package_dir, correct_relative_package_dir } => + write!( + f, + "{}: Incorrect directory location, should be {} instead.", + relative_package_dir.display(), + correct_relative_package_dir.display(), + ), + NixpkgsProblem::PackageNixNonExistent { relative_package_dir } => + write!( + f, + "{}: Missing required \"{PACKAGE_NIX_FILENAME}\" file.", + relative_package_dir.display(), + ), + NixpkgsProblem::PackageNixDir { relative_package_dir } => + write!( + f, + "{}: \"{PACKAGE_NIX_FILENAME}\" must be a file.", + relative_package_dir.display(), + ), + NixpkgsProblem::UndefinedAttr { relative_package_file, package_name } => + write!( + f, + "pkgs.{package_name}: This attribute is not defined but it should be defined automatically as {}", + relative_package_file.display() + ), + NixpkgsProblem::WrongCallPackage { relative_package_file, package_name } => + write!( + f, + "pkgs.{package_name}: This attribute is manually defined (most likely in pkgs/top-level/all-packages.nix), which is only allowed if the definition is of the form `pkgs.callPackage {} {{ ... }}` with a non-empty second argument.", + relative_package_file.display() + ), + NixpkgsProblem::NonDerivation { relative_package_file, package_name } => + write!( + f, + "pkgs.{package_name}: This attribute defined by {} is not a derivation", + relative_package_file.display() + ), + NixpkgsProblem::OutsideSymlink { relative_package_dir, subpath } => + write!( + f, + "{}: Path {} is a symlink pointing to a path outside the directory of that package.", + relative_package_dir.display(), + subpath.display(), + ), + NixpkgsProblem::UnresolvableSymlink { relative_package_dir, subpath, io_error } => + write!( + f, + "{}: Path {} is a symlink which cannot be resolved: {io_error}.", + relative_package_dir.display(), + subpath.display(), + ), + NixpkgsProblem::CouldNotParseNix { relative_package_dir, subpath, error } => + write!( + f, + "{}: File {} could not be parsed by rnix: {}", + relative_package_dir.display(), + subpath.display(), + error, + ), + NixpkgsProblem::PathInterpolation { relative_package_dir, subpath, line, text } => + write!( + f, + "{}: File {} at line {line} contains the path expression \"{}\", which is not yet supported and may point outside the directory of that package.", + relative_package_dir.display(), + subpath.display(), + text + ), + NixpkgsProblem::SearchPath { relative_package_dir, subpath, line, text } => + write!( + f, + "{}: File {} at line {line} contains the nix search path expression \"{}\" which may point outside the directory of that package.", + relative_package_dir.display(), + subpath.display(), + text + ), + NixpkgsProblem::OutsidePathReference { relative_package_dir, subpath, line, text } => + write!( + f, + "{}: File {} at line {line} contains the path expression \"{}\" which may point outside the directory of that package.", + relative_package_dir.display(), + subpath.display(), + text, + ), + NixpkgsProblem::UnresolvablePathReference { relative_package_dir, subpath, line, text, io_error } => + write!( + f, + "{}: File {} at line {line} contains the path expression \"{}\" which cannot be resolved: {io_error}.", + relative_package_dir.display(), + subpath.display(), + text, + ), + } + } +} diff --git a/pkgs/test/nixpkgs-check-by-name/src/references.rs b/pkgs/test/nixpkgs-check-by-name/src/references.rs index a6bc53d717d79..37837a54ddc28 100644 --- a/pkgs/test/nixpkgs-check-by-name/src/references.rs +++ b/pkgs/test/nixpkgs-check-by-name/src/references.rs @@ -1,5 +1,6 @@ use crate::check_result; -use crate::check_result::{CheckProblem, CheckResult}; +use crate::check_result::CheckResult; +use crate::nixpkgs_problem::NixpkgsProblem; use crate::utils; use crate::utils::LineIndex; @@ -47,7 +48,7 @@ fn check_path(context: &PackageContext, subpath: &Path) -> CheckResult<()> { // No need to handle the case of it being inside the directory, since we scan through the // entire directory recursively anyways if let Err(_prefix_error) = target.strip_prefix(context.absolute_package_dir) { - CheckProblem::OutsideSymlink { + NixpkgsProblem::OutsideSymlink { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), } @@ -56,7 +57,7 @@ fn check_path(context: &PackageContext, subpath: &Path) -> CheckResult<()> { check_result::ok(()) } } - Err(io_error) => CheckProblem::UnresolvableSymlink { + Err(io_error) => NixpkgsProblem::UnresolvableSymlink { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), io_error, @@ -104,7 +105,7 @@ fn check_nix_file(context: &PackageContext, subpath: &Path) -> CheckResult<()> { let root = Root::parse(&contents); if let Some(error) = root.errors().first() { - return CheckProblem::CouldNotParseNix { + return NixpkgsProblem::CouldNotParseNix { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), error: error.clone(), @@ -124,7 +125,7 @@ fn check_nix_file(context: &PackageContext, subpath: &Path) -> CheckResult<()> { } else if node.children().count() != 0 { // Filters out ./foo/${bar}/baz // TODO: We can just check ./foo - CheckProblem::PathInterpolation { + NixpkgsProblem::PathInterpolation { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), line, @@ -133,7 +134,7 @@ fn check_nix_file(context: &PackageContext, subpath: &Path) -> CheckResult<()> { .into_result() } else if text.starts_with('<') { // Filters out search paths like - CheckProblem::SearchPath { + NixpkgsProblem::SearchPath { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), line, @@ -149,7 +150,7 @@ fn check_nix_file(context: &PackageContext, subpath: &Path) -> CheckResult<()> { // No need to handle the case of it being inside the directory, since we scan through the // entire directory recursively anyways if let Err(_prefix_error) = target.strip_prefix(context.absolute_package_dir) { - CheckProblem::OutsidePathReference { + NixpkgsProblem::OutsidePathReference { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), line, @@ -160,7 +161,7 @@ fn check_nix_file(context: &PackageContext, subpath: &Path) -> CheckResult<()> { check_result::ok(()) } } - Err(e) => CheckProblem::UnresolvablePathReference { + Err(e) => NixpkgsProblem::UnresolvablePathReference { relative_package_dir: context.relative_package_dir.clone(), subpath: subpath.to_path_buf(), line, diff --git a/pkgs/test/nixpkgs-check-by-name/src/structure.rs b/pkgs/test/nixpkgs-check-by-name/src/structure.rs index 90a552a388637..b69f6211c0a05 100644 --- a/pkgs/test/nixpkgs-check-by-name/src/structure.rs +++ b/pkgs/test/nixpkgs-check-by-name/src/structure.rs @@ -1,10 +1,13 @@ use crate::check_result; -use crate::check_result::{CheckProblem, CheckResult}; +use crate::check_result::CheckResult; +use crate::nixpkgs_problem::NixpkgsProblem; use crate::references; use crate::utils; use crate::utils::{BASE_SUBPATH, PACKAGE_NIX_FILENAME}; +use itertools::concat; use lazy_static::lazy_static; use regex::Regex; +use std::fs::DirEntry; use std::path::{Path, PathBuf}; lazy_static! { @@ -30,8 +33,8 @@ pub fn relative_file_for_package(package_name: &str) -> PathBuf { relative_dir_for_package(package_name).join(PACKAGE_NIX_FILENAME) } -/// Read the structure of a Nixpkgs directory, displaying errors on the writer. -/// May return early with I/O errors. +/// Check the structure of Nixpkgs, returning the attribute names that are defined in +/// `pkgs/by-name` pub fn check_structure(path: &Path) -> CheckResult> { let base_dir = path.join(BASE_SUBPATH); @@ -46,7 +49,7 @@ pub fn check_structure(path: &Path) -> CheckResult> { // README.md is allowed to be a file and not checked check_result::ok(vec![]) } else if !shard_path.is_dir() { - CheckProblem::ShardNonDir { + NixpkgsProblem::ShardNonDir { relative_shard_path: relative_shard_path.clone(), } .into_result() @@ -54,7 +57,7 @@ pub fn check_structure(path: &Path) -> CheckResult> { } else { let shard_name_valid = SHARD_NAME_REGEX.is_match(&shard_name); let result = if !shard_name_valid { - CheckProblem::InvalidShardName { + NixpkgsProblem::InvalidShardName { relative_shard_path: relative_shard_path.clone(), shard_name: shard_name.clone(), } @@ -72,7 +75,7 @@ pub fn check_structure(path: &Path) -> CheckResult> { l.file_name().to_ascii_lowercase() == r.file_name().to_ascii_lowercase() }) .map(|(l, r)| { - CheckProblem::CaseSensitiveDuplicate { + NixpkgsProblem::CaseSensitiveDuplicate { relative_shard_path: relative_shard_path.clone(), first: l.file_name(), second: r.file_name(), @@ -83,84 +86,87 @@ pub fn check_structure(path: &Path) -> CheckResult> { let result = check_result::and(result, check_result::sequence_(duplicate_results)); let package_results = entries.into_iter().map(|package_entry| { - let package_path = package_entry.path(); - let package_name = package_entry.file_name().to_string_lossy().into_owned(); - let relative_package_dir = - PathBuf::from(format!("{BASE_SUBPATH}/{shard_name}/{package_name}")); - - if !package_path.is_dir() { - CheckProblem::PackageNonDir { - relative_package_dir: relative_package_dir.clone(), - } - .into_result() - } else { - let package_name_valid = PACKAGE_NAME_REGEX.is_match(&package_name); - let result = if !package_name_valid { - CheckProblem::InvalidPackageName { - relative_package_dir: relative_package_dir.clone(), - package_name: package_name.clone(), - } - .into_result() - } else { - check_result::ok(()) - }; - - let correct_relative_package_dir = relative_dir_for_package(&package_name); - let result = check_result::and( - result, - if relative_package_dir != correct_relative_package_dir { - // Only show this error if we have a valid shard and package name - // Because if one of those is wrong, you should fix that first - if shard_name_valid && package_name_valid { - CheckProblem::IncorrectShard { - relative_package_dir: relative_package_dir.clone(), - correct_relative_package_dir: correct_relative_package_dir - .clone(), - } - .into_result() - } else { - check_result::ok(()) - } - } else { - check_result::ok(()) - }, - ); - - let package_nix_path = package_path.join(PACKAGE_NIX_FILENAME); - let result = check_result::and( - result, - if !package_nix_path.exists() { - CheckProblem::PackageNixNonExistent { - relative_package_dir: relative_package_dir.clone(), - } - .into_result() - } else if package_nix_path.is_dir() { - CheckProblem::PackageNixDir { - relative_package_dir: relative_package_dir.clone(), - } - .into_result() - } else { - check_result::ok(()) - }, - ); - - let result = check_result::and( - result, - references::check_references( - &relative_package_dir, - &path.join(&relative_package_dir), - ), - ); - - check_result::map(result, |_| package_name.clone()) - } + check_package(path, &shard_name, shard_name_valid, package_entry) }); check_result::and(result, check_result::sequence(package_results)) } }); - check_result::map(check_result::sequence(shard_results), |x| { - x.into_iter().flatten().collect::>() - }) + // Combine the package names conatained within each shard into a longer list + check_result::map(check_result::sequence(shard_results), concat) +} + +fn check_package( + path: &Path, + shard_name: &str, + shard_name_valid: bool, + package_entry: DirEntry, +) -> CheckResult { + let package_path = package_entry.path(); + let package_name = package_entry.file_name().to_string_lossy().into_owned(); + let relative_package_dir = PathBuf::from(format!("{BASE_SUBPATH}/{shard_name}/{package_name}")); + + if !package_path.is_dir() { + NixpkgsProblem::PackageNonDir { + relative_package_dir: relative_package_dir.clone(), + } + .into_result() + } else { + let package_name_valid = PACKAGE_NAME_REGEX.is_match(&package_name); + let result = if !package_name_valid { + NixpkgsProblem::InvalidPackageName { + relative_package_dir: relative_package_dir.clone(), + package_name: package_name.clone(), + } + .into_result() + } else { + check_result::ok(()) + }; + + let correct_relative_package_dir = relative_dir_for_package(&package_name); + let result = check_result::and( + result, + if relative_package_dir != correct_relative_package_dir { + // Only show this error if we have a valid shard and package name + // Because if one of those is wrong, you should fix that first + if shard_name_valid && package_name_valid { + NixpkgsProblem::IncorrectShard { + relative_package_dir: relative_package_dir.clone(), + correct_relative_package_dir: correct_relative_package_dir.clone(), + } + .into_result() + } else { + check_result::ok(()) + } + } else { + check_result::ok(()) + }, + ); + + let package_nix_path = package_path.join(PACKAGE_NIX_FILENAME); + let result = check_result::and( + result, + if !package_nix_path.exists() { + NixpkgsProblem::PackageNixNonExistent { + relative_package_dir: relative_package_dir.clone(), + } + .into_result() + } else if package_nix_path.is_dir() { + NixpkgsProblem::PackageNixDir { + relative_package_dir: relative_package_dir.clone(), + } + .into_result() + } else { + check_result::ok(()) + }, + ); + + let result = check_result::and( + result, + references::check_references(&relative_package_dir, &path.join(&relative_package_dir)), + ); + + check_result::map(result, |_| package_name.clone()) + } } -- cgit 1.4.1