From eaa936920b17c0bfb697c28bb3ab60f0f346da3b Mon Sep 17 00:00:00 2001 From: milkory Date: Wed, 9 Apr 2025 08:33:12 +0800 Subject: [PATCH 1/3] fix exec multi at root path --- src/find/mod.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/find/mod.rs b/src/find/mod.rs index f3008faf..f3ef7c71 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -179,6 +179,7 @@ fn process_dir( // As WalkDir seems not providing a function to check its stack, // using current_dir is a workaround to check leaving directory. let mut current_dir: Option = None; + let mut depth = 0; while let Some(result) = it.next() { match WalkEntry::from_walkdir(result, config.follow) { Err(err) => { @@ -188,11 +189,16 @@ fn process_dir( Ok(entry) => { let mut matcher_io = matchers::MatcherIO::new(deps); - let new_dir = entry.path().parent().map(|x| x.to_path_buf()); - if new_dir != current_dir { + let new_dir = entry + .path() + .parent() + .or_else(|| Some(entry.path())) + .map(|x| x.to_path_buf()); + if entry.depth() != depth || new_dir != current_dir { if let Some(dir) = current_dir.take() { matcher.finished_dir(dir.as_path(), &mut matcher_io); } + depth = entry.depth(); current_dir = new_dir; } From 33852adee3c903e4ffa9757a9ab5fb13caa908e0 Mon Sep 17 00:00:00 2001 From: milkory Date: Mon, 14 Apr 2025 00:13:40 +0800 Subject: [PATCH 2/3] add tests for process_dir and execdir + --- src/find/mod.rs | 50 ++++++++++++++++++++++++++++++++++++++++ tests/find_exec_tests.rs | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/src/find/mod.rs b/src/find/mod.rs index f3ef7c71..70ee75e7 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -333,6 +333,7 @@ pub fn find_main(args: &[&str], deps: &dyn Dependencies) -> i32 { #[cfg(test)] mod tests { + use std::cell::Cell; use std::fs; use std::io::{Cursor, ErrorKind, Read}; use std::time::Duration; @@ -347,6 +348,7 @@ mod tests { use crate::find::matchers::time::ChangeTime; use crate::find::matchers::MatcherIO; + use super::matchers::Matcher; use super::*; #[cfg(windows)] @@ -403,6 +405,37 @@ mod tests { } } + // A fake matcher struct that records finished and finished_dir arguments. + pub struct FakeMatcher { + pub finished_dir_result: RefCell>, + pub finished_result: Cell, + } + + impl FakeMatcher { + pub fn new() -> Self { + Self { + finished_dir_result: RefCell::new(Vec::new()), + finished_result: Cell::new(0), + } + } + } + + impl Matcher for FakeMatcher { + fn matches(&self, _: &WalkEntry, _: &mut MatcherIO) -> bool { + true + } + + fn finished_dir(&self, finished_directory: &std::path::Path, _: &mut MatcherIO) { + self.finished_dir_result + .borrow_mut() + .push(finished_directory.to_path_buf()); + } + + fn finished(&self, _: &mut MatcherIO) { + self.finished_result.set(self.finished_result.get() + 1); + } + } + fn create_file_link() { #[cfg(unix)] if let Err(e) = symlink("abbbc", "test_data/links/link-f") { @@ -1540,4 +1573,21 @@ mod tests { assert_eq!(rc, 0); } + + #[test] + fn test_finished_in_root_directory() { + let mut config = Config::default(); + config.max_depth = 1; + + let deps = FakeDependencies::new(); + let mut quit = false; + let matcher = FakeMatcher::new(); + process_dir("/", &config, &deps, &matcher, &mut quit); + + let dir_result = matcher.finished_dir_result.borrow(); + assert_eq!(dir_result.len(), 2); + assert_eq!(dir_result[0], PathBuf::from("/")); + assert_eq!(dir_result[1], PathBuf::from("/")); + assert_eq!(matcher.finished_result.get(), 1); + } } diff --git a/tests/find_exec_tests.rs b/tests/find_exec_tests.rs index 510a6939..6bf4ea70 100644 --- a/tests/find_exec_tests.rs +++ b/tests/find_exec_tests.rs @@ -208,3 +208,43 @@ fn find_execdir_multi() { )) ); } + +#[test] +fn find_execdir_multi_in_root_directory() { + let temp_dir = Builder::new() + .prefix("find_execdir_multi_in_root_directory") + .tempdir() + .unwrap(); + let temp_dir_path = temp_dir.path().to_string_lossy(); + let deps = FakeDependencies::new(); + // only look at files because the "size" of a directory is a system (and filesystem) + // dependent thing and we want these tests to be universal. + let rc = find_main( + &[ + "find", + &fix_up_slashes("/"), + "-maxdepth", + "0", + "-execdir", + &path_to_testing_commandline(), + temp_dir_path.as_ref(), + "--sort", + ")", + "{}", + "+", + ], + &deps, + ); + + assert_eq!(rc, 0); + // exec has side effects, so we won't output anything unless -print is + // explicitly passed in. + assert_eq!(deps.get_output_as_string(), ""); + + // check the executable ran as expected + let mut f = File::open(temp_dir.path().join("1.txt")).expect("Failed to open output file"); + let mut s = String::new(); + f.read_to_string(&mut s) + .expect("failed to read output file"); + assert_eq!(s, "cwd=/\nargs=\n)\n--sort\n/\n"); +} From d02dcbca96c0f5868d7e640a646216ca61e63149 Mon Sep 17 00:00:00 2001 From: milkory Date: Mon, 14 Apr 2025 00:25:26 +0800 Subject: [PATCH 3/3] fix up test on windows --- src/find/mod.rs | 7 ++++--- tests/find_exec_tests.rs | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/find/mod.rs b/src/find/mod.rs index 70ee75e7..08ccc05b 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -1576,9 +1576,10 @@ mod tests { #[test] fn test_finished_in_root_directory() { - let mut config = Config::default(); - config.max_depth = 1; - + let config = Config { + max_depth: 1, + ..Default::default() + }; let deps = FakeDependencies::new(); let mut quit = false; let matcher = FakeMatcher::new(); diff --git a/tests/find_exec_tests.rs b/tests/find_exec_tests.rs index 6bf4ea70..5629f86f 100644 --- a/tests/find_exec_tests.rs +++ b/tests/find_exec_tests.rs @@ -217,12 +217,19 @@ fn find_execdir_multi_in_root_directory() { .unwrap(); let temp_dir_path = temp_dir.path().to_string_lossy(); let deps = FakeDependencies::new(); + + let cwd = env::current_dir().expect("no current directory"); + let root_dir = cwd + .ancestors() + .last() + .expect("current directory has no root"); + // only look at files because the "size" of a directory is a system (and filesystem) // dependent thing and we want these tests to be universal. let rc = find_main( &[ "find", - &fix_up_slashes("/"), + &fix_up_slashes(&root_dir.to_string_lossy()), "-maxdepth", "0", "-execdir", @@ -246,5 +253,12 @@ fn find_execdir_multi_in_root_directory() { let mut s = String::new(); f.read_to_string(&mut s) .expect("failed to read output file"); - assert_eq!(s, "cwd=/\nargs=\n)\n--sort\n/\n"); + assert_eq!( + s, + fix_up_slashes(&format!( + "cwd={}\nargs=\n)\n--sort\n{}\n", + root_dir.to_string_lossy(), + root_dir.to_string_lossy(), + )) + ); }