summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs43
-rw-r--r--src/normalizer.rs37
2 files changed, 63 insertions, 17 deletions
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<R: Read, W: Write>(
}
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<R: Read, W: Write>(
#[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<u8> {
+ 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<PathBuf, NormalizeError> {
+ pub fn normalize(&self, input: &Path) -> Result<NormalizedPath, NormalizeError> {
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<PathBuf, NormalizeError> {
/// # 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")
+ );
}
}