diff options
Diffstat (limited to 'src/path_list_editor.rs')
| -rw-r--r-- | src/path_list_editor.rs | 144 |
1 files changed, 130 insertions, 14 deletions
diff --git a/src/path_list_editor.rs b/src/path_list_editor.rs index 9addb7f..8d789a4 100644 --- a/src/path_list_editor.rs +++ b/src/path_list_editor.rs @@ -3,8 +3,11 @@ use std::{ ffi::{OsStr, OsString}, io::{Read, Write}, os::unix::ffi::OsStrExt, + path::{Path, PathBuf}, }; +use crate::normalizer::Normalizer; + const NUL: &[u8] = b"\0"; pub fn append_paths<R: Read, W: Write>( @@ -59,17 +62,22 @@ pub fn prepend_paths<R: Read, W: Write>( pub fn remove_paths<R: Read, W: Write>( mut input: R, mut output: W, - unwanted_paths: &[OsString], -) -> std::io::Result<()> { - let mut buf = Vec::new(); - input.read_to_end(&mut buf)?; - let unwanted_paths = HashSet::<&OsString>::from_iter(unwanted_paths); - for segment in buf.split(|b| *b == 0) { + unwanted_paths: &[PathBuf], + normalizer: &Normalizer, +) -> Result<(), Box<dyn std::error::Error>> { + let mut input_buf = Vec::new(); + input.read_to_end(&mut input_buf)?; + let unwanted_paths = unwanted_paths + .iter() + .map(|path| normalizer.normalize(path)) + .collect::<Result<HashSet<_>, _>>()?; + for segment in input_buf.split(|b| *b == 0) { if segment.is_empty() { continue; } - let os_string_segment = OsStr::from_bytes(segment).to_os_string(); - if !unwanted_paths.contains(&os_string_segment) { + let os_string_segment = OsStr::from_bytes(segment); + let normalized_path = normalizer.normalize(Path::new(os_string_segment))?; + if !unwanted_paths.contains(&normalized_path) { output.write_all(segment)?; output.write_all(NUL)?; } @@ -79,10 +87,20 @@ pub fn remove_paths<R: Read, W: Write>( #[cfg(test)] mod tests { - use std::ffi::OsString; + use std::{ + ffi::OsString, + path::{Path, PathBuf}, + }; + + use crate::normalizer::Normalizer; use super::{append_paths, prepend_paths, remove_paths}; + fn get_normalizer() -> Normalizer { + let default_path = Path::new("."); + Normalizer::new(default_path, default_path).unwrap() + } + #[test] fn append_paths_works_with_empty_stdin_and_args() { let input = b""; @@ -218,7 +236,7 @@ mod tests { let input = b""; let mut output = Vec::new(); - remove_paths(&input[..], &mut output, &[]).unwrap(); + remove_paths(&input[..], &mut output, &[], &get_normalizer()).unwrap(); assert_eq!(output, b""); } @@ -228,7 +246,7 @@ mod tests { let input = b"README.md\0"; let mut output = Vec::new(); - remove_paths(&input[..], &mut output, &[]).unwrap(); + remove_paths(&input[..], &mut output, &[], &get_normalizer()).unwrap(); assert_eq!(output, b"README.md\0"); } @@ -238,7 +256,13 @@ mod tests { let input = b""; let mut output = Vec::new(); - remove_paths(&input[..], &mut output, &[OsString::from("README.md")]).unwrap(); + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("README.md")], + &get_normalizer(), + ) + .unwrap(); assert_eq!(output, b""); } @@ -248,7 +272,13 @@ mod tests { let input = b"a.rs\0b.rs\0c.rs\0"; let mut output = Vec::new(); - remove_paths(&input[..], &mut output, &[OsString::from("b.rs")]).unwrap(); + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("b.rs")], + &get_normalizer(), + ) + .unwrap(); assert_eq!(output, b"a.rs\0c.rs\0"); } @@ -258,8 +288,94 @@ mod tests { let input = b"a.rs\0b.rs\0b.rs\0c.rs\0"; let mut output = Vec::new(); - remove_paths(&input[..], &mut output, &[OsString::from("b.rs")]).unwrap(); + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("b.rs")], + &get_normalizer(), + ) + .unwrap(); assert_eq!(output, b"a.rs\0c.rs\0"); } + + #[test] + fn remove_paths_matches_dot_normalized_entries() { + let input = b"src/./main.rs\0src/lib.rs\0"; + let mut output = Vec::new(); + + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("src/main.rs")], + &get_normalizer(), + ) + .unwrap(); + + assert_eq!(output, b"src/lib.rs\0"); + } + + #[test] + fn remove_paths_matches_parent_dir_normalized_entries() { + let input = b"src/../a.rs\0b.rs\0"; + let mut output = Vec::new(); + + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("a.rs")], + &get_normalizer(), + ) + .unwrap(); + + assert_eq!(output, b"b.rs\0"); + } + + #[test] + fn remove_paths_matches_when_unwanted_path_needs_normalization() { + let input = b"a.rs\0b.rs\0"; + let mut output = Vec::new(); + + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("src/../a.rs")], + &get_normalizer(), + ) + .unwrap(); + + assert_eq!(output, b"b.rs\0"); + } + + #[test] + fn remove_paths_matches_when_both_sides_need_normalization() { + let input = b"src/../a.rs\0b.rs\0"; + let mut output = Vec::new(); + + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("./a.rs")], + &get_normalizer(), + ) + .unwrap(); + + assert_eq!(output, b"b.rs\0"); + } + + #[test] + fn remove_paths_preserves_original_bytes_for_kept_paths() { + let input = b"src/./main.rs\0src/lib.rs\0"; + let mut output = Vec::new(); + + remove_paths( + &input[..], + &mut output, + &[PathBuf::from("other.rs")], + &get_normalizer(), + ) + .unwrap(); + + assert_eq!(output, b"src/./main.rs\0src/lib.rs\0"); + } } |
