about summary refs log tree commit diff
path: root/pkgs/test/nixpkgs-check-by-name
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2024-03-01 02:29:24 +0100
committerSilvan Mosberger <silvan.mosberger@tweag.io>2024-03-01 23:07:34 +0100
commit5981aff2125baba1430e5a96338a71e2e1fad18d (patch)
tree7dff7c45829a009d483e8aa17849aed4eac9d406 /pkgs/test/nixpkgs-check-by-name
parent7858f062884e2318dda212ab7cc1ceda871195b2 (diff)
downloadnixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.tar
nixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.tar.gz
nixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.tar.bz2
nixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.tar.lz
nixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.tar.xz
nixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.tar.zst
nixlib-5981aff2125baba1430e5a96338a71e2e1fad18d.zip
tests.nixpkgs-check-by-name: Use RelativePath for relative paths
Makes the code easier to understand and less error-prone
Diffstat (limited to 'pkgs/test/nixpkgs-check-by-name')
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/eval.rs26
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/nix_file.rs17
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs196
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/ratchet.rs4
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/references.rs52
-rw-r--r--pkgs/test/nixpkgs-check-by-name/src/structure.rs16
6 files changed, 158 insertions, 153 deletions
diff --git a/pkgs/test/nixpkgs-check-by-name/src/eval.rs b/pkgs/test/nixpkgs-check-by-name/src/eval.rs
index 978fe9295336..094508f595d8 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/eval.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/eval.rs
@@ -8,6 +8,7 @@ use crate::utils;
 use crate::validation::ResultIteratorExt as _;
 use crate::validation::{self, Validation::Success};
 use crate::NixFileStore;
+use relative_path::RelativePathBuf;
 use std::path::Path;
 
 use anyhow::Context;
@@ -56,18 +57,15 @@ struct Location {
 
 impl Location {
     // Returns the [file] field, but relative to Nixpkgs
-    fn relative_file(&self, nixpkgs_path: &Path) -> anyhow::Result<PathBuf> {
-        Ok(self
-            .file
-            .strip_prefix(nixpkgs_path)
-            .with_context(|| {
-                format!(
-                    "The file ({}) is outside Nixpkgs ({})",
-                    self.file.display(),
-                    nixpkgs_path.display()
-                )
-            })?
-            .to_path_buf())
+    fn relative_file(&self, nixpkgs_path: &Path) -> anyhow::Result<RelativePathBuf> {
+        let path = self.file.strip_prefix(nixpkgs_path).with_context(|| {
+            format!(
+                "The file ({}) is outside Nixpkgs ({})",
+                self.file.display(),
+                nixpkgs_path.display()
+            )
+        })?;
+        Ok(RelativePathBuf::from_path(path).expect("relative path"))
     }
 }
 
@@ -352,12 +350,12 @@ fn by_name(
 /// all-packages.nix
 fn by_name_override(
     attribute_name: &str,
-    expected_package_file: PathBuf,
+    expected_package_file: RelativePathBuf,
     is_semantic_call_package: bool,
     optional_syntactic_call_package: Option<CallPackageArgumentInfo>,
     definition: String,
     location: Location,
-    relative_location_file: PathBuf,
+    relative_location_file: RelativePathBuf,
 ) -> validation::Validation<ratchet::RatchetState<ratchet::ManualDefinition>> {
     // At this point, we completed two different checks for whether it's a
     // `callPackage`
diff --git a/pkgs/test/nixpkgs-check-by-name/src/nix_file.rs b/pkgs/test/nixpkgs-check-by-name/src/nix_file.rs
index 1cb5d1c0d08d..e2dc1e196141 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/nix_file.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/nix_file.rs
@@ -3,6 +3,7 @@
 use crate::utils::LineIndex;
 use anyhow::Context;
 use itertools::Either::{self, Left, Right};
+use relative_path::RelativePathBuf;
 use rnix::ast;
 use rnix::ast::Expr;
 use rnix::ast::HasEntry;
@@ -79,7 +80,7 @@ impl NixFile {
 #[derive(Debug, PartialEq)]
 pub struct CallPackageArgumentInfo {
     /// The relative path of the first argument, or `None` if it's not a path.
-    pub relative_path: Option<PathBuf>,
+    pub relative_path: Option<RelativePathBuf>,
     /// Whether the second argument is an empty attribute set
     pub empty_arg: bool,
 }
@@ -369,8 +370,8 @@ pub enum ResolvedPath {
     /// The path is outside the given absolute path
     Outside,
     /// The path is within the given absolute path.
-    /// The `PathBuf` is the relative path under the given absolute path.
-    Within(PathBuf),
+    /// The `RelativePathBuf` is the relative path under the given absolute path.
+    Within(RelativePathBuf),
 }
 
 impl NixFile {
@@ -402,7 +403,9 @@ impl NixFile {
                 // Check if it's within relative_to
                 match resolved.strip_prefix(relative_to) {
                     Err(_prefix_error) => ResolvedPath::Outside,
-                    Ok(suffix) => ResolvedPath::Within(suffix.to_path_buf()),
+                    Ok(suffix) => ResolvedPath::Within(
+                        RelativePathBuf::from_path(suffix).expect("a relative path"),
+                    ),
                 }
             }
         }
@@ -506,14 +509,14 @@ mod tests {
             (
                 6,
                 Some(CallPackageArgumentInfo {
-                    relative_path: Some(PathBuf::from("file.nix")),
+                    relative_path: Some(RelativePathBuf::from("file.nix")),
                     empty_arg: true,
                 }),
             ),
             (
                 7,
                 Some(CallPackageArgumentInfo {
-                    relative_path: Some(PathBuf::from("file.nix")),
+                    relative_path: Some(RelativePathBuf::from("file.nix")),
                     empty_arg: true,
                 }),
             ),
@@ -527,7 +530,7 @@ mod tests {
             (
                 9,
                 Some(CallPackageArgumentInfo {
-                    relative_path: Some(PathBuf::from("file.nix")),
+                    relative_path: Some(RelativePathBuf::from("file.nix")),
                     empty_arg: false,
                 }),
             ),
diff --git a/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs b/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
index 498284ac6f24..f9e232b93933 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/nixpkgs_problem.rs
@@ -2,139 +2,140 @@ use crate::structure;
 use crate::utils::PACKAGE_NIX_FILENAME;
 use indoc::writedoc;
 use relative_path::RelativePath;
+use relative_path::RelativePathBuf;
 use std::ffi::OsString;
 use std::fmt;
-use std::path::Path;
-use std::path::PathBuf;
 
 /// Any problem that can occur when checking Nixpkgs
+/// All paths are relative to Nixpkgs such that the error messages can't be influenced by Nixpkgs absolute
+/// location
 #[derive(Clone)]
 pub enum NixpkgsProblem {
     ShardNonDir {
-        relative_shard_path: PathBuf,
+        relative_shard_path: RelativePathBuf,
     },
     InvalidShardName {
-        relative_shard_path: PathBuf,
+        relative_shard_path: RelativePathBuf,
         shard_name: String,
     },
     PackageNonDir {
-        relative_package_dir: PathBuf,
+        relative_package_dir: RelativePathBuf,
     },
     CaseSensitiveDuplicate {
-        relative_shard_path: PathBuf,
+        relative_shard_path: RelativePathBuf,
         first: OsString,
         second: OsString,
     },
     InvalidPackageName {
-        relative_package_dir: PathBuf,
+        relative_package_dir: RelativePathBuf,
         package_name: String,
     },
     IncorrectShard {
-        relative_package_dir: PathBuf,
-        correct_relative_package_dir: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        correct_relative_package_dir: RelativePathBuf,
     },
     PackageNixNonExistent {
-        relative_package_dir: PathBuf,
+        relative_package_dir: RelativePathBuf,
     },
     PackageNixDir {
-        relative_package_dir: PathBuf,
+        relative_package_dir: RelativePathBuf,
     },
     UndefinedAttr {
-        relative_package_file: PathBuf,
+        relative_package_file: RelativePathBuf,
         package_name: String,
     },
     EmptyArgument {
         package_name: String,
-        file: PathBuf,
+        file: RelativePathBuf,
         line: usize,
         column: usize,
         definition: String,
     },
     NonToplevelCallPackage {
         package_name: String,
-        file: PathBuf,
+        file: RelativePathBuf,
         line: usize,
         column: usize,
         definition: String,
     },
     NonPath {
         package_name: String,
-        file: PathBuf,
+        file: RelativePathBuf,
         line: usize,
         column: usize,
         definition: String,
     },
     WrongCallPackagePath {
         package_name: String,
-        file: PathBuf,
+        file: RelativePathBuf,
         line: usize,
-        actual_path: PathBuf,
-        expected_path: PathBuf,
+        actual_path: RelativePathBuf,
+        expected_path: RelativePathBuf,
     },
     NonSyntacticCallPackage {
         package_name: String,
-        file: PathBuf,
+        file: RelativePathBuf,
         line: usize,
         column: usize,
         definition: String,
     },
     NonDerivation {
-        relative_package_file: PathBuf,
+        relative_package_file: RelativePathBuf,
         package_name: String,
     },
     OutsideSymlink {
-        relative_package_dir: PathBuf,
-        subpath: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        subpath: RelativePathBuf,
     },
     UnresolvableSymlink {
-        relative_package_dir: PathBuf,
-        subpath: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        subpath: RelativePathBuf,
         io_error: String,
     },
     PathInterpolation {
-        relative_package_dir: PathBuf,
-        subpath: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        subpath: RelativePathBuf,
         line: usize,
         text: String,
     },
     SearchPath {
-        relative_package_dir: PathBuf,
-        subpath: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        subpath: RelativePathBuf,
         line: usize,
         text: String,
     },
     OutsidePathReference {
-        relative_package_dir: PathBuf,
-        subpath: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        subpath: RelativePathBuf,
         line: usize,
         text: String,
     },
     UnresolvablePathReference {
-        relative_package_dir: PathBuf,
-        subpath: PathBuf,
+        relative_package_dir: RelativePathBuf,
+        subpath: RelativePathBuf,
         line: usize,
         text: String,
         io_error: String,
     },
     MovedOutOfByNameEmptyArg {
         package_name: String,
-        call_package_path: Option<PathBuf>,
-        file: PathBuf,
+        call_package_path: Option<RelativePathBuf>,
+        file: RelativePathBuf,
     },
     MovedOutOfByNameNonEmptyArg {
         package_name: String,
-        call_package_path: Option<PathBuf>,
-        file: PathBuf,
+        call_package_path: Option<RelativePathBuf>,
+        file: RelativePathBuf,
     },
     NewPackageNotUsingByNameEmptyArg {
         package_name: String,
-        call_package_path: Option<PathBuf>,
-        file: PathBuf,
+        call_package_path: Option<RelativePathBuf>,
+        file: RelativePathBuf,
     },
     NewPackageNotUsingByNameNonEmptyArg {
         package_name: String,
-        call_package_path: Option<PathBuf>,
-        file: PathBuf,
+        call_package_path: Option<RelativePathBuf>,
+        file: RelativePathBuf,
     },
     InternalCallPackageUsed {
         attr_name: String,
@@ -151,56 +152,56 @@ impl fmt::Display for NixpkgsProblem {
                 write!(
                     f,
                     "{}: This is a file, but it should be a directory.",
-                    relative_shard_path.display(),
+                    relative_shard_path,
                 ),
             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()
+                    relative_shard_path,
                 ),
             NixpkgsProblem::PackageNonDir { relative_package_dir } =>
                 write!(
                     f,
                     "{}: This path is a file, but it should be a directory.",
-                    relative_package_dir.display(),
+                    relative_package_dir,
                 ),
             NixpkgsProblem::CaseSensitiveDuplicate { relative_shard_path, first, second } =>
                 write!(
                     f,
                     "{}: Duplicate case-sensitive package directories {first:?} and {second:?}.",
-                    relative_shard_path.display(),
+                    relative_shard_path,
                 ),
             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(),
+                    relative_package_dir,
                 ),
             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(),
+                    relative_package_dir,
+                    correct_relative_package_dir,
                 ),
             NixpkgsProblem::PackageNixNonExistent { relative_package_dir } =>
                 write!(
                     f,
                     "{}: Missing required \"{PACKAGE_NIX_FILENAME}\" file.",
-                    relative_package_dir.display(),
+                    relative_package_dir,
                 ),
             NixpkgsProblem::PackageNixDir { relative_package_dir } =>
                 write!(
                     f,
                     "{}: \"{PACKAGE_NIX_FILENAME}\" must be a file.",
-                    relative_package_dir.display(),
+                    relative_package_dir,
                 ),
             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()
+                    relative_package_file,
                 ),
             NixpkgsProblem::EmptyArgument { package_name, file, line, column, definition } =>
                 writedoc!(
@@ -216,9 +217,9 @@ impl fmt::Display for NixpkgsProblem {
 
                       Such a definition is provided automatically and therefore not necessary. Please remove it.
                     ",
-                    structure::relative_dir_for_package(package_name).display(),
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_dir_for_package(package_name),
+                    structure::relative_file_for_package(package_name),
+                    file,
                     line,
                     indent_definition(*column, definition.clone()),
                 ),
@@ -234,9 +235,9 @@ impl fmt::Display for NixpkgsProblem {
 
                     {}
                     ",
-                    structure::relative_dir_for_package(package_name).display(),
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_dir_for_package(package_name),
+                    structure::relative_file_for_package(package_name),
+                    file,
                     line,
                     indent_definition(*column, definition.clone()),
                 ),
@@ -252,9 +253,9 @@ impl fmt::Display for NixpkgsProblem {
 
                     {}
                     ",
-                    structure::relative_dir_for_package(package_name).display(),
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_dir_for_package(package_name),
+                    structure::relative_file_for_package(package_name),
+                    file,
                     line,
                     indent_definition(*column, definition.clone()),
                 ),
@@ -270,9 +271,9 @@ impl fmt::Display for NixpkgsProblem {
 
                         {package_name} = callPackage {} {{ /* ... */ }};
                     ",
-                    structure::relative_dir_for_package(package_name).display(),
+                    structure::relative_dir_for_package(package_name),
                     create_path_expr(file, expected_path),
-                    file.display(), line,
+                    file, line,
                     create_path_expr(file, actual_path),
                 },
             NixpkgsProblem::NonSyntacticCallPackage { package_name, file, line, column, definition } => {
@@ -287,9 +288,9 @@ impl fmt::Display for NixpkgsProblem {
 
                     {}
                     ",
-                    structure::relative_dir_for_package(package_name).display(),
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_dir_for_package(package_name),
+                    structure::relative_file_for_package(package_name),
+                    file,
                     line,
                     indent_definition(*column, definition.clone()),
                 )
@@ -298,58 +299,58 @@ impl fmt::Display for NixpkgsProblem {
                 write!(
                     f,
                     "pkgs.{package_name}: This attribute defined by {} is not a derivation",
-                    relative_package_file.display()
+                    relative_package_file,
                 ),
             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(),
+                    relative_package_dir,
+                    subpath,
                 ),
             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(),
+                    relative_package_dir,
+                    subpath,
                 ),
             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(),
+                    relative_package_dir,
+                    subpath,
                     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(),
+                    relative_package_dir,
+                    subpath,
                     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(),
+                    relative_package_dir,
+                    subpath,
                     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(),
+                    relative_package_dir,
+                    subpath,
                     text,
                 ),
             NixpkgsProblem::MovedOutOfByNameEmptyArg { package_name, call_package_path, file } => {
                 let call_package_arg =
                     if let Some(path) = &call_package_path {
-                        format!("./{}", path.display())
+                        format!("./{}", path)
                     } else {
                         "...".into()
                     };
@@ -359,14 +360,14 @@ impl fmt::Display for NixpkgsProblem {
                     - Attribute `pkgs.{package_name}` was previously defined in {}, but is now manually defined as `callPackage {call_package_arg} {{ /* ... */ }}` in {}.
                       Please move the package back and remove the manual `callPackage`.
                     ",
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_file_for_package(package_name),
+                    file,
                     )
             },
             NixpkgsProblem::MovedOutOfByNameNonEmptyArg { package_name, call_package_path, file } => {
                 let call_package_arg =
                     if let Some(path) = &call_package_path {
-                        format!("./{}", path.display())
+                        format!("./{}", path)
                     } else {
                         "...".into()
                     };
@@ -378,14 +379,14 @@ impl fmt::Display for NixpkgsProblem {
                     - Attribute `pkgs.{package_name}` was previously defined in {}, but is now manually defined as `callPackage {call_package_arg} {{ ... }}` in {}.
                       While the manual `callPackage` is still needed, it's not necessary to move the package files.
                     ",
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_file_for_package(package_name),
+                    file,
                     )
             },
             NixpkgsProblem::NewPackageNotUsingByNameEmptyArg { package_name, call_package_path, file } => {
                 let call_package_arg =
                     if let Some(path) = &call_package_path {
-                        format!("./{}", path.display())
+                        format!("./{}", path)
                     } else {
                         "...".into()
                     };
@@ -397,14 +398,14 @@ impl fmt::Display for NixpkgsProblem {
                       See `pkgs/by-name/README.md` for more details.
                       Since the second `callPackage` argument is `{{ }}`, no manual `callPackage` in {} is needed anymore.
                     ",
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_file_for_package(package_name),
+                    file,
                 )
             },
             NixpkgsProblem::NewPackageNotUsingByNameNonEmptyArg { package_name, call_package_path, file } => {
                 let call_package_arg =
                     if let Some(path) = &call_package_path {
-                        format!("./{}", path.display())
+                        format!("./{}", path)
                     } else {
                         "...".into()
                     };
@@ -416,8 +417,8 @@ impl fmt::Display for NixpkgsProblem {
                       See `pkgs/by-name/README.md` for more details.
                       Since the second `callPackage` argument is not `{{ }}`, the manual `callPackage` in {} is still needed.
                     ",
-                    structure::relative_file_for_package(package_name).display(),
-                    file.display(),
+                    structure::relative_file_for_package(package_name),
+                    file,
                 )
             },
             NixpkgsProblem::InternalCallPackageUsed { attr_name } =>
@@ -448,14 +449,13 @@ fn indent_definition(column: usize, definition: String) -> String {
 }
 
 /// Creates a Nix path expression that when put into Nix file `from_file`, would point to the `to_file`.
-fn create_path_expr(from_file: impl AsRef<Path>, to_file: impl AsRef<Path>) -> String {
-    // These `expect` calls should never trigger because we only call this function with
-    // relative paths that have a parent. That's why we `expect` them!
-    let from = RelativePath::from_path(&from_file)
-        .expect("a relative path")
-        .parent()
-        .expect("a parent for this path");
-    let to = RelativePath::from_path(&to_file).expect("a path");
-    let rel = from.relative(to);
+fn create_path_expr(
+    from_file: impl AsRef<RelativePath>,
+    to_file: impl AsRef<RelativePath>,
+) -> String {
+    // This `expect` calls should never trigger because we only call this function with files.
+    // That's why we `expect` them!
+    let from = from_file.as_ref().parent().expect("a parent for this path");
+    let rel = from.relative(to_file);
     format!("./{rel}")
 }
diff --git a/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs b/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
index eed5071a5a2a..8136d641c351 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/ratchet.rs
@@ -5,8 +5,8 @@
 use crate::nix_file::CallPackageArgumentInfo;
 use crate::nixpkgs_problem::NixpkgsProblem;
 use crate::validation::{self, Validation, Validation::Success};
+use relative_path::RelativePathBuf;
 use std::collections::HashMap;
-use std::path::PathBuf;
 
 /// The ratchet value for the entirety of Nixpkgs.
 #[derive(Default)]
@@ -146,7 +146,7 @@ impl ToNixpkgsProblem for ManualDefinition {
 pub enum UsesByName {}
 
 impl ToNixpkgsProblem for UsesByName {
-    type ToContext = (CallPackageArgumentInfo, PathBuf);
+    type ToContext = (CallPackageArgumentInfo, RelativePathBuf);
 
     fn to_nixpkgs_problem(
         name: &str,
diff --git a/pkgs/test/nixpkgs-check-by-name/src/references.rs b/pkgs/test/nixpkgs-check-by-name/src/references.rs
index b716b99099c4..e2319163ccc6 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/references.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/references.rs
@@ -2,6 +2,7 @@ use crate::nixpkgs_problem::NixpkgsProblem;
 use crate::utils;
 use crate::validation::{self, ResultIteratorExt, Validation::Success};
 use crate::NixFileStore;
+use relative_path::RelativePath;
 
 use anyhow::Context;
 use rowan::ast::AstNode;
@@ -12,14 +13,14 @@ use std::path::Path;
 /// Both symlinks and Nix path expressions are checked.
 pub fn check_references(
     nix_file_store: &mut NixFileStore,
-    relative_package_dir: &Path,
+    relative_package_dir: &RelativePath,
     absolute_package_dir: &Path,
 ) -> validation::Result<()> {
     // The first subpath to check is the package directory itself, which we can represent as an
     // empty path, since the absolute package directory gets prepended to this.
     // We don't use `./.` to keep the error messages cleaner
     // (there's no canonicalisation going on underneath)
-    let subpath = Path::new("");
+    let subpath = RelativePath::new("");
     check_path(
         nix_file_store,
         relative_package_dir,
@@ -29,7 +30,7 @@ pub fn check_references(
     .with_context(|| {
         format!(
             "While checking the references in package directory {}",
-            relative_package_dir.display()
+            relative_package_dir
         )
     })
 }
@@ -41,11 +42,11 @@ pub fn check_references(
 /// The absolute package directory gets prepended before doing anything with it though.
 fn check_path(
     nix_file_store: &mut NixFileStore,
-    relative_package_dir: &Path,
+    relative_package_dir: &RelativePath,
     absolute_package_dir: &Path,
-    subpath: &Path,
+    subpath: &RelativePath,
 ) -> validation::Result<()> {
-    let path = absolute_package_dir.join(subpath);
+    let path = subpath.to_path(absolute_package_dir);
 
     Ok(if path.is_symlink() {
         // Check whether the symlink resolves to outside the package directory
@@ -55,8 +56,8 @@ fn check_path(
                 // entire directory recursively anyways
                 if let Err(_prefix_error) = target.strip_prefix(absolute_package_dir) {
                     NixpkgsProblem::OutsideSymlink {
-                        relative_package_dir: relative_package_dir.to_path_buf(),
-                        subpath: subpath.to_path_buf(),
+                        relative_package_dir: relative_package_dir.to_owned(),
+                        subpath: subpath.to_owned(),
                     }
                     .into()
                 } else {
@@ -64,8 +65,8 @@ fn check_path(
                 }
             }
             Err(io_error) => NixpkgsProblem::UnresolvableSymlink {
-                relative_package_dir: relative_package_dir.to_path_buf(),
-                subpath: subpath.to_path_buf(),
+                relative_package_dir: relative_package_dir.to_owned(),
+                subpath: subpath.to_owned(),
                 io_error: io_error.to_string(),
             }
             .into(),
@@ -80,11 +81,12 @@ fn check_path(
                         nix_file_store,
                         relative_package_dir,
                         absolute_package_dir,
-                        &subpath.join(entry.file_name()),
+                        // TODO: The relative_path crate doesn't seem to support OsStr
+                        &subpath.join(entry.file_name().to_string_lossy().to_string()),
                     )
                 })
                 .collect_vec()
-                .with_context(|| format!("Error while recursing into {}", subpath.display()))?,
+                .with_context(|| format!("Error while recursing into {}", subpath))?,
         )
     } else if path.is_file() {
         // Only check Nix files
@@ -96,7 +98,7 @@ fn check_path(
                     absolute_package_dir,
                     subpath,
                 )
-                .with_context(|| format!("Error while checking Nix file {}", subpath.display()))?
+                .with_context(|| format!("Error while checking Nix file {}", subpath))?
             } else {
                 Success(())
             }
@@ -105,7 +107,7 @@ fn check_path(
         }
     } else {
         // This should never happen, git doesn't support other file types
-        anyhow::bail!("Unsupported file type for path {}", subpath.display());
+        anyhow::bail!("Unsupported file type for path {}", subpath);
     })
 }
 
@@ -113,11 +115,11 @@ fn check_path(
 /// directory
 fn check_nix_file(
     nix_file_store: &mut NixFileStore,
-    relative_package_dir: &Path,
+    relative_package_dir: &RelativePath,
     absolute_package_dir: &Path,
-    subpath: &Path,
+    subpath: &RelativePath,
 ) -> validation::Result<()> {
-    let path = absolute_package_dir.join(subpath);
+    let path = subpath.to_path(absolute_package_dir);
 
     let nix_file = nix_file_store.get(&path)?;
 
@@ -135,29 +137,29 @@ fn check_nix_file(
 
             match nix_file.static_resolve_path(path, absolute_package_dir) {
                 ResolvedPath::Interpolated => NixpkgsProblem::PathInterpolation {
-                    relative_package_dir: relative_package_dir.to_path_buf(),
-                    subpath: subpath.to_path_buf(),
+                    relative_package_dir: relative_package_dir.to_owned(),
+                    subpath: subpath.to_owned(),
                     line,
                     text,
                 }
                 .into(),
                 ResolvedPath::SearchPath => NixpkgsProblem::SearchPath {
-                    relative_package_dir: relative_package_dir.to_path_buf(),
-                    subpath: subpath.to_path_buf(),
+                    relative_package_dir: relative_package_dir.to_owned(),
+                    subpath: subpath.to_owned(),
                     line,
                     text,
                 }
                 .into(),
                 ResolvedPath::Outside => NixpkgsProblem::OutsidePathReference {
-                    relative_package_dir: relative_package_dir.to_path_buf(),
-                    subpath: subpath.to_path_buf(),
+                    relative_package_dir: relative_package_dir.to_owned(),
+                    subpath: subpath.to_owned(),
                     line,
                     text,
                 }
                 .into(),
                 ResolvedPath::Unresolvable(e) => NixpkgsProblem::UnresolvablePathReference {
-                    relative_package_dir: relative_package_dir.to_path_buf(),
-                    subpath: subpath.to_path_buf(),
+                    relative_package_dir: relative_package_dir.to_owned(),
+                    subpath: subpath.to_owned(),
                     line,
                     text,
                     io_error: e.to_string(),
diff --git a/pkgs/test/nixpkgs-check-by-name/src/structure.rs b/pkgs/test/nixpkgs-check-by-name/src/structure.rs
index 9b615dd9969a..09806bc3d4dc 100644
--- a/pkgs/test/nixpkgs-check-by-name/src/structure.rs
+++ b/pkgs/test/nixpkgs-check-by-name/src/structure.rs
@@ -7,8 +7,9 @@ use crate::NixFileStore;
 use itertools::concat;
 use lazy_static::lazy_static;
 use regex::Regex;
+use relative_path::RelativePathBuf;
 use std::fs::DirEntry;
-use std::path::{Path, PathBuf};
+use std::path::Path;
 
 lazy_static! {
     static ref SHARD_NAME_REGEX: Regex = Regex::new(r"^[a-z0-9_-]{1,2}$").unwrap();
@@ -21,15 +22,15 @@ pub fn shard_for_package(package_name: &str) -> String {
     package_name.to_lowercase().chars().take(2).collect()
 }
 
-pub fn relative_dir_for_shard(shard_name: &str) -> PathBuf {
-    PathBuf::from(format!("{BASE_SUBPATH}/{shard_name}"))
+pub fn relative_dir_for_shard(shard_name: &str) -> RelativePathBuf {
+    RelativePathBuf::from(format!("{BASE_SUBPATH}/{shard_name}"))
 }
 
-pub fn relative_dir_for_package(package_name: &str) -> PathBuf {
+pub fn relative_dir_for_package(package_name: &str) -> RelativePathBuf {
     relative_dir_for_shard(&shard_for_package(package_name)).join(package_name)
 }
 
-pub fn relative_file_for_package(package_name: &str) -> PathBuf {
+pub fn relative_file_for_package(package_name: &str) -> RelativePathBuf {
     relative_dir_for_package(package_name).join(PACKAGE_NIX_FILENAME)
 }
 
@@ -120,7 +121,8 @@ fn check_package(
 ) -> validation::Result<String> {
     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}"));
+    let relative_package_dir =
+        RelativePathBuf::from(format!("{BASE_SUBPATH}/{shard_name}/{package_name}"));
 
     Ok(if !package_path.is_dir() {
         NixpkgsProblem::PackageNonDir {
@@ -174,7 +176,7 @@ fn check_package(
         let result = result.and(references::check_references(
             nix_file_store,
             &relative_package_dir,
-            &path.join(&relative_package_dir),
+            &relative_package_dir.to_path(path),
         )?);
 
         result.map(|_| package_name.clone())