use std::path::{Path, PathBuf};
pub(crate) fn candidate(workspace: &Path, relative: &Path) -> Option<PathBuf> {
(!relative.as_os_str().is_empty()).then(|| workspace.join(relative))
}
pub(crate) fn same_dir(left: &Path, right: &Path) -> bool {
match (left.canonicalize(), right.canonicalize()) {
(Ok(left), Ok(right)) => left == right,
_ => left == right,
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn an_empty_relative_path_names_no_candidate() {
assert_eq!(candidate(Path::new("/repo"), Path::new("")), None);
}
#[test]
fn a_named_relative_path_joins_the_workspace() {
assert_eq!(
candidate(Path::new("/repo"), Path::new(".basis/hooks.json")),
Some(PathBuf::from("/repo/.basis/hooks.json"))
);
}
#[test]
fn a_directory_is_itself() {
let dir = tempfile::tempdir().expect("tempdir");
assert!(same_dir(dir.path(), dir.path()));
}
#[test]
fn two_spellings_of_one_directory_match() {
let dir = tempfile::tempdir().expect("tempdir");
let indirect = dir.path().join("child").join("..");
std::fs::create_dir(dir.path().join("child")).expect("create child");
assert!(
same_dir(dir.path(), &indirect),
"a path that resolves to the same place is the same place"
);
}
#[test]
fn different_directories_do_not_match() {
let left = tempfile::tempdir().expect("tempdir");
let right = tempfile::tempdir().expect("tempdir");
assert!(!same_dir(left.path(), right.path()));
}
#[test]
fn unresolvable_paths_fall_back_to_comparing_as_written() {
let missing = PathBuf::from("/definitely/not/a/real/path");
assert!(same_dir(&missing, &missing));
assert!(!same_dir(&missing, &PathBuf::from("/also/not/real")));
}
}