From d41999a6e73edf29a87bc26648feab3ae23b50d2 Mon Sep 17 00:00:00 2001 From: A Farzat Date: Thu, 4 Jun 2026 16:58:20 +0300 Subject: Obtain absolute input path from Normalizer --- src/main.rs | 43 ++++++++++++++++++++++++++++++++++++++----- src/normalizer.rs | 37 +++++++++++++++++++++++++------------ 2 files changed, 63 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index b50dd73..d2da889 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,10 +29,10 @@ pub fn run( } let path = Path::new(OsStr::from_bytes(segment)); - let bytes = std::fs::read(origin_base.join(path))?; - let path = normalizer.normalize(path)?; + let normalized_path = normalizer.normalize(path)?; + let bytes = std::fs::read(normalized_path.absolute)?; - owned.push((path, bytes)); + owned.push((normalized_path.relative, bytes)); } // convert to expected renderer input @@ -48,10 +48,20 @@ pub fn run( #[cfg(test)] mod tests { - use super::run; - use std::fs; use std::io::Cursor; use std::path::Path; + use std::{env, fs}; + + use super::run; + + fn paths_to_null_sep_bytes(file_paths: &[&Path]) -> Vec { + let mut output = Vec::new(); + for path in file_paths { + output.extend(path.as_os_str().as_encoded_bytes()); + output.push(0); + } + output + } #[test] fn cli_with_empty_input_produces_empty_project() { @@ -156,4 +166,27 @@ mod tests { fs::remove_dir("sandbox/src").unwrap(); fs::remove_dir("sandbox").unwrap(); } + + #[test] + fn cli_ignores_origin_when_input_path_is_absolute() { + let temp_dir = env::temp_dir(); + let filepath = temp_dir.join("test_main.rs"); + fs::create_dir_all(temp_dir).unwrap(); + fs::write(&filepath, "fn main() {}").unwrap(); + + // stdin provides path relative to origin_base + let input = Cursor::new(paths_to_null_sep_bytes(&[&filepath])); + let mut output = Vec::new(); + let root = Path::new("project"); + let origin_base = Path::new("sandbox/src"); + + run(input, &mut output, root, origin_base).unwrap(); + + let output = String::from_utf8(output).unwrap(); + + // Must contain file content → proves correct reading + assert!(output.contains("fn main() {}")); + + fs::remove_file(filepath).unwrap(); + } } diff --git a/src/normalizer.rs b/src/normalizer.rs index d757512..a9714b3 100644 --- a/src/normalizer.rs +++ b/src/normalizer.rs @@ -4,6 +4,13 @@ use std::{ path::{Component, Path, PathBuf}, }; +pub struct NormalizedPath { + /// Path normalized and made absolute, suitable for filesystem access + pub absolute: PathBuf, + /// Path normalized and made relative to root, used as identifier + pub relative: PathBuf, +} + #[derive(Debug)] pub enum NormalizeError { EmptyInput, @@ -51,13 +58,16 @@ impl Normalizer { }) } - pub fn normalize(&self, input: &Path) -> Result { + pub fn normalize(&self, input: &Path) -> Result { if input.as_os_str().is_empty() { return Err(NormalizeError::EmptyInput); } let input = absolutize(input, &self.origin_base); let normalized_input = normalize_components(&input)?; - Ok(make_relative_to_root(normalized_input, &self.root)) + Ok(NormalizedPath { + relative: make_relative_to_root(&normalized_input, &self.root), + absolute: normalized_input, + }) } } @@ -129,7 +139,7 @@ fn normalize_components(path: &Path) -> Result { /// # Invariant /// `target` and `root` must be absolute paths. /// Violations indicate a bug in the caller. -fn make_relative_to_root(target: PathBuf, mut root: &Path) -> PathBuf { +fn make_relative_to_root(target: &Path, mut root: &Path) -> PathBuf { debug_assert!( target.is_absolute(), "Target must be an absolute path: {:?}", @@ -149,7 +159,7 @@ fn make_relative_to_root(target: PathBuf, mut root: &Path) -> PathBuf { upward.push(".."); root = new_root; } else { - return target; + return target.to_path_buf(); } } } @@ -173,7 +183,7 @@ mod tests { let fake_cwd = Path::new("/sandbox"); let normalizer = Normalizer::new_with_cwd(Path::new(""), Path::new(""), fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("main.rs")); - assert_eq!(result.unwrap(), Path::new("main.rs")); + assert_eq!(result.unwrap().relative, Path::new("main.rs")); } #[test] @@ -183,7 +193,7 @@ mod tests { let origin_base = Path::new("src"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("../main.rs")); - assert_eq!(result.unwrap(), Path::new("main.rs")); + assert_eq!(result.unwrap().relative, Path::new("main.rs")); } #[test] @@ -193,7 +203,7 @@ mod tests { let origin_base = Path::new("/project/src"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("main.rs")); - assert_eq!(result.unwrap(), Path::new("src/main.rs")); + assert_eq!(result.unwrap().relative, Path::new("src/main.rs")); } #[test] @@ -203,7 +213,7 @@ mod tests { let origin_base = Path::new("/outside"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("main.rs")); - assert_eq!(result.unwrap(), Path::new("../outside/main.rs")); + assert_eq!(result.unwrap().relative, Path::new("../outside/main.rs")); } #[test] @@ -213,7 +223,7 @@ mod tests { let origin_base = Path::new("/sandbox/outside"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("main.rs")); - assert_eq!(result.unwrap(), Path::new("../outside/main.rs")); + assert_eq!(result.unwrap().relative, Path::new("../outside/main.rs")); } #[test] @@ -223,7 +233,7 @@ mod tests { let origin_base = Path::new("/sandbox/outside"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("/sandbox/main.rs")); - assert_eq!(result.unwrap(), Path::new("../main.rs")); + assert_eq!(result.unwrap().relative, Path::new("../main.rs")); } #[test] @@ -233,7 +243,7 @@ mod tests { let origin_base = Path::new("outside"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("main.rs")); - assert_eq!(result.unwrap(), Path::new("../outside/main.rs")); + assert_eq!(result.unwrap().relative, Path::new("../outside/main.rs")); } #[test] @@ -256,6 +266,9 @@ mod tests { let origin_base = Path::new("outside"); let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd).unwrap(); let result = normalizer.normalize(Path::new("main.rs")); - assert_eq!(result.unwrap(), Path::new("../sandbox/outside/main.rs")); + assert_eq!( + result.unwrap().relative, + Path::new("../sandbox/outside/main.rs") + ); } } -- cgit v1.3.1