use std::path::{Path, PathBuf}; /// Resolves a (possibly relative) tool-supplied path against `cwd`. pub fn resolve(cwd: &Path, file_path: &str) -> PathBuf { let path = Path::new(file_path); if path.is_absolute() { path.to_path_buf() } else { cwd.join(path) } } /// Slash-separated path relative to `cwd`, used as the permission pattern — falls back to /// the absolute path (still slash-separated) when `path` isn't under `cwd`. pub fn relative_pattern(cwd: &Path, path: &Path) -> String { let rel = path.strip_prefix(cwd).unwrap_or(path); rel.to_string_lossy().replace('\\', "/") } #[cfg(test)] mod tests { use super::*; #[test] fn resolve_joins_relative_paths_to_cwd() { let cwd = Path::new("/home/user/project"); assert_eq!( resolve(cwd, "src/main.rs"), PathBuf::from("/home/user/project/src/main.rs") ); } #[test] fn resolve_leaves_absolute_paths_untouched() { let cwd = Path::new("/home/user/project"); assert_eq!(resolve(cwd, "/etc/hosts"), PathBuf::from("/etc/hosts")); } #[test] fn relative_pattern_strips_cwd_prefix() { let cwd = Path::new("/home/user/project"); let path = Path::new("/home/user/project/src/main.rs"); assert_eq!(relative_pattern(cwd, path), "src/main.rs"); } #[test] fn relative_pattern_falls_back_to_absolute_outside_cwd() { let cwd = Path::new("/home/user/project"); let path = Path::new("/etc/hosts"); assert_eq!(relative_pattern(cwd, path), "/etc/hosts"); } }