summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorA Farzat <a@farzat.xyz>2026-06-20 19:43:18 +0300
committerA Farzat <a@farzat.xyz>2026-06-20 19:58:06 +0300
commit43454f5035be9b07e71596dfddad271db5061495 (patch)
treeb9144cf2898708db437cf23974a5af44eae71f10 /src
parentf54df9fd6d50030beee064bfd1415bad066107d2 (diff)
downloadrepo2markdown-43454f5035be9b07e71596dfddad271db5061495.tar.gz
repo2markdown-43454f5035be9b07e71596dfddad271db5061495.zip
Make remove_paths take origin_base directly
Passing normalizer makes both the binary and tests complicated without reducing the complexity of the function signature.
Diffstat (limited to 'src')
-rw-r--r--src/bin/r2md-remove.rs6
-rw-r--r--src/path_list_editor.rs67
2 files changed, 42 insertions, 31 deletions
diff --git a/src/bin/r2md-remove.rs b/src/bin/r2md-remove.rs
index 0835668..07c9124 100644
--- a/src/bin/r2md-remove.rs
+++ b/src/bin/r2md-remove.rs
@@ -1,7 +1,7 @@
use std::{io, path::PathBuf};
use clap::Parser;
-use repo2markdown::{normalizer::Normalizer, path_list_editor::remove_paths};
+use repo2markdown::path_list_editor::remove_paths;
/// Remove paths from a null-separated file list from stdin.
#[derive(Debug, Parser)]
@@ -18,13 +18,11 @@ struct Cli {
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
- let normalizer = Normalizer::new(&cli.origin, &cli.origin)?;
-
remove_paths(
io::stdin().lock(),
io::stdout().lock(),
&cli.paths,
- &normalizer,
+ &cli.origin,
)
}
diff --git a/src/path_list_editor.rs b/src/path_list_editor.rs
index bdd6982..1ae4816 100644
--- a/src/path_list_editor.rs
+++ b/src/path_list_editor.rs
@@ -5,14 +5,14 @@
//! `r2md-prepend`, and `r2md-remove`.
//!
//! Paths that are kept from stdin are written back using their original byte representation.
-//! Removal compares paths after normalization using the supplied [`Normalizer`].
+//! Removal compares paths after normalization relative to a supplied origin base.
use std::{
collections::HashSet,
ffi::OsString,
io::{Read, Write},
os::unix::ffi::OsStrExt,
- path::PathBuf,
+ path::{Path, PathBuf},
};
use crate::{normalizer::Normalizer, util::path_list::paths_from_null_separated_bytes};
@@ -95,28 +95,29 @@ pub fn prepend_paths<R: Read, W: Write>(
/// Removes paths from a null-separated path list.
///
/// The `input` stream is interpreted as a NUL-separated sequence of path entries. Each entry is
-/// normalized with `normalizer` and compared against the normalized form of each path in
+/// normalized relative to `origin_base` and compared against the normalized form of each path in
/// `unwanted_paths`.
///
/// Entries whose normalized path matches one of the normalized `unwanted_paths` are skipped.
/// Entries that are kept are written to `output` using their original byte form, followed by a NUL
/// byte.
-///
-/// Matching is normalization-aware, so paths such as `src/../a.rs`, `./a.rs`, and an absolute path
-/// to `a.rs` may match depending on the supplied [`Normalizer`]. This function does not deduplicate
-/// kept entries.
pub fn remove_paths<R: Read, W: Write>(
mut input: R,
mut output: W,
unwanted_paths: &[PathBuf],
- normalizer: &Normalizer,
+ origin_base: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
- let mut input_buf = Vec::new();
- input.read_to_end(&mut input_buf)?;
+ // The root is arbitrary here because root_relative is not user-facing.
+ // It only needs to be consistent across both sides of the comparison.
+ let normalizer = Normalizer::new(Path::new("."), origin_base)?;
+ // Normalize unwanted paths once and place them in a HashSet for efficient lookup.
let unwanted_paths = unwanted_paths
.iter()
.map(|path| normalizer.normalize(path))
.collect::<Result<HashSet<_>, _>>()?;
+
+ let mut input_buf = Vec::new();
+ input.read_to_end(&mut input_buf)?;
for path in paths_from_null_separated_bytes(&input_buf) {
let normalized_path = normalizer.normalize(path)?;
if !unwanted_paths.contains(&normalized_path) {
@@ -131,18 +132,12 @@ pub fn remove_paths<R: Read, W: Write>(
mod tests {
use std::{
ffi::OsString,
+ os::unix::ffi::OsStrExt,
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"";
@@ -278,7 +273,7 @@ mod tests {
let input = b"";
let mut output = Vec::new();
- remove_paths(&input[..], &mut output, &[], &get_normalizer()).unwrap();
+ remove_paths(&input[..], &mut output, &[], Path::new(".")).unwrap();
assert_eq!(output, b"");
}
@@ -288,7 +283,7 @@ mod tests {
let input = b"README.md\0";
let mut output = Vec::new();
- remove_paths(&input[..], &mut output, &[], &get_normalizer()).unwrap();
+ remove_paths(&input[..], &mut output, &[], Path::new(".")).unwrap();
assert_eq!(output, b"README.md\0");
}
@@ -302,7 +297,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("README.md")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -318,7 +313,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("b.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -334,7 +329,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("b.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -350,7 +345,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("src/main.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -366,7 +361,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("a.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -382,7 +377,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("src/../a.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -398,7 +393,7 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("./a.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
@@ -414,10 +409,28 @@ mod tests {
&input[..],
&mut output,
&[PathBuf::from("other.rs")],
- &get_normalizer(),
+ Path::new("."),
)
.unwrap();
assert_eq!(output, b"src/./main.rs\0src/lib.rs\0");
}
+
+ #[test]
+ fn remove_paths_matches_relative_unwanted_path_against_absolute_input_using_origin_base() {
+ let temp_dir = tempfile::tempdir().unwrap();
+ let origin = temp_dir.path();
+ let absolute_path = origin.join("a.rs");
+
+ let mut input = Vec::new();
+ input.extend(absolute_path.as_os_str().as_bytes());
+ input.push(0);
+ input.extend(b"b.rs\0");
+
+ let mut output = Vec::new();
+
+ remove_paths(&input[..], &mut output, &[PathBuf::from("a.rs")], origin).unwrap();
+
+ assert_eq!(output, b"b.rs\0");
+ }
}