From a2ccf993970284e2f19fcb74b66013a7dd6c7319 Mon Sep 17 00:00:00 2001 From: A Farzat Date: Tue, 2 Jun 2026 16:10:43 +0300 Subject: Make normalize return paths relative to root This is still not complete, as it panics if target_path is not reachable from root. --- src/lib.rs | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fa6b1a9..9e9afcf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,11 @@ -use std::path::{Path, PathBuf, Component}; +use std::path::{Component, Path, PathBuf}; #[derive(Debug)] pub enum NormalizeError { EmptyInput, } -pub fn normalize_path( - _root: &Path, - origin: &Path, - input: &Path, -) -> Result { +pub fn normalize_path(root: &Path, origin: &Path, input: &Path) -> Result { if input.as_os_str().is_empty() { return Err(NormalizeError::EmptyInput); } @@ -18,13 +14,26 @@ pub fn normalize_path( for component in origin_joint_input.components() { match component { Component::CurDir => (), - Component::ParentDir => { stack.pop(); }, - Component::Prefix(_) => { stack.push(component); }, - Component::Normal(_) => { stack.push(component); }, - Component::RootDir => { stack.push(component) }, + Component::ParentDir => { + stack.pop(); + } + Component::Prefix(_) => stack.push(component), + Component::Normal(_) => stack.push(component), + Component::RootDir => stack.push(component), } } - Ok(PathBuf::from_iter(stack)) + let normalized_origin_join_input = PathBuf::from_iter(stack); + Ok(normalize_to_root(&normalized_origin_join_input, root)) +} + +fn normalize_to_root(target_path: &Path, root: &Path,) -> PathBuf { + match target_path.strip_prefix(root) { + Ok(normalized_path) => normalized_path.to_path_buf(), + Err(_) => { + let root_parent = root.parent().expect("failed cuz target_path is not absolute"); + PathBuf::from("..").join(normalize_to_root(target_path, root_parent)) + }, + } } #[cfg(test)] @@ -61,4 +70,22 @@ mod tests { assert!(result.is_ok()); assert_eq!(result.unwrap(), Path::new("main.rs")); } + + #[test] + fn path_is_made_relative_to_root() { + let root = Path::new("/project"); + let origin_dir = Path::new("/project/src"); + let input = Path::new("main.rs"); + let result = normalize_path(root, origin_dir, input); + assert_eq!(result.unwrap(), Path::new("src/main.rs")); + } + + #[test] + fn path_is_made_relative_to_root_from_outside() { + let root = Path::new("/project"); + let origin_dir = Path::new("/outside"); + let input = Path::new("main.rs"); + let result = normalize_path(root, origin_dir, input); + assert_eq!(result.unwrap(), Path::new("../outside/main.rs")); + } } -- cgit v1.3.1