diff --git a/README.md b/README.md index 3e1e9fd..807b457 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ The following checks are performed when calling the binary: - `pkgs/by-name` must only contain subdirectories of the form `${shard}/${name}`, called _package directories_. - The `name`'s of package directories must be unique when lowercased. - `name` is a string only consisting of the ASCII characters `a-z`, `A-Z`, `0-9`, `-` or `_`. +- `name` only starts with an ASCII character `a-z`, `A-Z`, `-` or `_`. - `shard` is the lowercased first two letters of `name`, expressed in Nix: `shard = toLower (substring 0 2 name)`. - Each package directory must contain a `package.nix` file and may contain arbitrary other files. diff --git a/src/problem/mod.rs b/src/problem/mod.rs index 981c0ea..0550903 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -34,6 +34,8 @@ pub mod npv_161; pub mod npv_162; pub mod npv_163; +pub mod npv_170; + #[derive(Clone, Display, EnumFrom)] pub enum Problem { /// NPV-100: attribute is not defined but it should be defined automatically @@ -123,6 +125,9 @@ pub enum Problem { NewTopLevelPackageShouldBeByNameWithCustomArgument( npv_163::NewTopLevelPackageShouldBeByNameWithCustomArgument, ), + + /// NPV-170: by-name package cannot be number prefixed + ByNamePackegPrefixedWithNumber(npv_170::ByNamePackegPrefixedWithNumber), } fn indent_definition(column: usize, definition: &str) -> String { diff --git a/src/problem/npv_170.rs b/src/problem/npv_170.rs new file mode 100644 index 0000000..c540051 --- /dev/null +++ b/src/problem/npv_170.rs @@ -0,0 +1,25 @@ +use std::fmt; + +use derive_new::new; +use relative_path::RelativePathBuf; + +#[derive(Clone, new)] +pub struct ByNamePackegPrefixedWithNumber { + #[new(into)] + package_name: String, + #[new(into)] + relative_package_dir: RelativePathBuf, +} + +impl fmt::Display for ByNamePackegPrefixedWithNumber { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let Self { + package_name, + relative_package_dir, + } = self; + write!( + f, + "- {relative_package_dir}: Attribute `{package_name}` should not be number-prefixed. Prefix with `_`, or wrap in quotes" + ) + } +} diff --git a/src/structure.rs b/src/structure.rs index 93b5975..966326d 100644 --- a/src/structure.rs +++ b/src/structure.rs @@ -7,7 +7,9 @@ use lazy_static::lazy_static; use regex::Regex; use relative_path::RelativePathBuf; -use crate::problem::{npv_109, npv_110, npv_111, npv_140, npv_141, npv_142, npv_143, npv_144}; +use crate::problem::{ + npv_109, npv_110, npv_111, npv_140, npv_141, npv_142, npv_143, npv_144, npv_170, +}; use crate::references; use crate::validation::{self, ResultIteratorExt, Validation::Success}; use crate::NixFileStore; @@ -16,8 +18,9 @@ pub const BASE_SUBPATH: &str = "pkgs/by-name"; pub const PACKAGE_NIX_FILENAME: &str = "package.nix"; lazy_static! { - static ref SHARD_NAME_REGEX: Regex = Regex::new(r"^[a-z0-9_-]{1,2}$").unwrap(); - static ref PACKAGE_NAME_REGEX: Regex = Regex::new(r"^[a-zA-Z0-9_-]+$").unwrap(); + static ref SHARD_NAME_REGEX: Regex = Regex::new(r"^((_[0-9])|([a-z][a-z0-9_-]?))$").unwrap(); + static ref PACKAGE_NAME_REGEX: Regex = + Regex::new(r"^((_[0-9])|[a-zA-Z])[a-zA-Z0-9_-]*$").unwrap(); } /// Deterministic file listing so that tests are reproducible. @@ -137,11 +140,19 @@ fn check_package( } else { let package_name_valid = PACKAGE_NAME_REGEX.is_match(&package_name); let result = if !package_name_valid { - npv_141::InvalidPackageDirectoryName::new( - package_name.clone(), - relative_package_dir.clone(), - ) - .into() + if package_name.starts_with(|c: char| c.is_ascii_digit()) { + npv_170::ByNamePackegPrefixedWithNumber::new( + package_name.clone(), + relative_package_dir.clone(), + ) + .into() + } else { + npv_141::InvalidPackageDirectoryName::new( + package_name.clone(), + relative_package_dir.clone(), + ) + .into() + } } else { Success(()) }; diff --git a/tests/by-name-numprefix/default.nix b/tests/by-name-numprefix/default.nix new file mode 100644 index 0000000..861260c --- /dev/null +++ b/tests/by-name-numprefix/default.nix @@ -0,0 +1 @@ +import { root = ./.; } diff --git a/tests/by-name-numprefix/expected b/tests/by-name-numprefix/expected new file mode 100644 index 0000000..38342a6 --- /dev/null +++ b/tests/by-name-numprefix/expected @@ -0,0 +1,2 @@ +- pkgs/by-name/_1/10foo: Attribute `10foo` should not be number-prefixed. Prefix with `_`, or wrap in quotes +This PR introduces the problems listed above. Please fix them before merging, otherwise the base branch would break. diff --git a/tests/by-name-numprefix/pkgs/by-name/_1/10foo/package.nix b/tests/by-name-numprefix/pkgs/by-name/_1/10foo/package.nix new file mode 100644 index 0000000..ce29e51 --- /dev/null +++ b/tests/by-name-numprefix/pkgs/by-name/_1/10foo/package.nix @@ -0,0 +1 @@ +{ someDrv }: SomeDrv