From da3bd2342d22f9bcd7ba0a89cbbfb5b96c140f0e Mon Sep 17 00:00:00 2001 From: Stephan Boyer Date: Sat, 20 Jun 2026 00:01:05 -0700 Subject: [PATCH 1/2] Modernize dependency API usage --- src/directive.rs | 20 ++++++-------- src/main.rs | 2 +- src/walk.rs | 69 +++++++++++++++++++++++------------------------- 3 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/directive.rs b/src/directive.rs index 2e54826..0e3b4e0 100644 --- a/src/directive.rs +++ b/src/directive.rs @@ -75,11 +75,10 @@ pub fn parse( if let Ok(line) = line_result { // Tags for captures in tag_regex.captures_iter(&line) { - // If we got a match, then `captures.get(1)` is guaranteed to return a `Some`. Hence - // we are justified in unwrapping. + let (_, [label]) = captures.extract(); tags.push(Directive { r#type: Type::Tag, - label: captures.get(1).unwrap().as_str().to_owned(), + label: label.to_owned(), path: path.to_owned(), line_number: line_number + 1, }); @@ -87,11 +86,10 @@ pub fn parse( // Refs for captures in ref_regex.captures_iter(&line) { - // If we got a match, then `captures.get(1)` is guaranteed to return a `Some`. Hence - // we are justified in unwrapping. + let (_, [label]) = captures.extract(); refs.push(Directive { r#type: Type::Ref, - label: captures.get(1).unwrap().as_str().to_owned(), + label: label.to_owned(), path: path.to_owned(), line_number: line_number + 1, }); @@ -99,11 +97,10 @@ pub fn parse( // Files for captures in file_regex.captures_iter(&line) { - // If we got a match, then `captures.get(1)` is guaranteed to return a `Some`. Hence - // we are justified in unwrapping. + let (_, [label]) = captures.extract(); files.push(Directive { r#type: Type::File, - label: captures.get(1).unwrap().as_str().to_owned(), + label: label.to_owned(), path: path.to_owned(), line_number: line_number + 1, }); @@ -111,11 +108,10 @@ pub fn parse( // Directories for captures in dir_regex.captures_iter(&line) { - // If we got a match, then `captures.get(1)` is guaranteed to return a `Some`. Hence - // we are justified in unwrapping. + let (_, [label]) = captures.extract(); dirs.push(Directive { r#type: Type::Dir, - label: captures.get(1).unwrap().as_str().to_owned(), + label: label.to_owned(), path: path.to_owned(), line_number: line_number + 1, }); diff --git a/src/main.rs b/src/main.rs index 5fed314..e644055 100644 --- a/src/main.rs +++ b/src/main.rs @@ -115,7 +115,7 @@ fn entry() -> Result<(), String> { let ignore_rules = config.ignore_rules; let project_root_clone = project_root.clone(); let files_scanned = walk::walk( - std::slice::from_ref(&project_root), + &project_root, &project_root, &ignore_rules, move |file_path, file| { diff --git a/src/walk.rs b/src/walk.rs index e710017..be96d89 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -4,7 +4,7 @@ use ignore::{ }; use std::{ fs::File, - path::{Path, PathBuf}, + path::Path, sync::{ Arc, atomic::{AtomicUsize, Ordering}, @@ -15,7 +15,7 @@ use std::{ // and the file. It skips files which cannot be read (e.g., due to lack of permissions). It also // skips over symlinks. The number of files traversed is returned. pub fn walk( - paths: &[PathBuf], + path: &Path, current_dir: &Path, ignore_rules: &[String], callback: T, @@ -24,44 +24,41 @@ pub fn walk( let files_scanned = Arc::new(AtomicUsize::new(0)); let overrides = build_overrides(current_dir, ignore_rules)?; - // Scan each of the given paths. - for path in paths { - // Traverse the filesystem in parallel. - WalkBuilder::new(path) - .current_dir(current_dir) - .hidden(false) - .require_git(false) - .parents(false) - .overrides(overrides.clone()) - .build_parallel() - .run(|| { - // These clones will be moved into the closure below, and that closure will be sent - // to a new thread. - let mut callback = callback.clone(); - let files_scanned = files_scanned.clone(); + // Traverse the filesystem in parallel. + WalkBuilder::new(path) + .current_dir(current_dir) + .hidden(false) + .require_git(false) + .parents(false) + .overrides(overrides) + .build_parallel() + .run(|| { + // These clones will be moved into the closure below, and that closure will be sent + // to a new thread. + let mut callback = callback.clone(); + let files_scanned = files_scanned.clone(); - // This closure will be sent to a new thread. - Box::new(move |result| { - // Proceed if we have access to the path. - if let Ok(dir_entry) = result { - // Here, `file_type()` should always return a `Some`. It could only return - // `None` if the file represents STDIN, and that isn't the case here. - if dir_entry.file_type().unwrap().is_file() { - // Try to open the file. - let possible_file = File::open(dir_entry.path()); - if let Ok(file) = possible_file { - // Process the file and increment the counter. - callback(dir_entry.path(), file); - files_scanned.fetch_add(1, Ordering::SeqCst); - } + // This closure will be sent to a new thread. + Box::new(move |result| { + // Proceed if we have access to the path. + if let Ok(dir_entry) = result { + // Here, `file_type()` should always return a `Some`. It could only return + // `None` if the file represents STDIN, and that isn't the case here. + if dir_entry.file_type().unwrap().is_file() { + // Try to open the file. + let possible_file = File::open(dir_entry.path()); + if let Ok(file) = possible_file { + // Process the file and increment the counter. + callback(dir_entry.path(), file); + files_scanned.fetch_add(1, Ordering::SeqCst); } } + } - // Don't stop...believing! - WalkState::Continue - }) - }); - } + // Don't stop...believing! + WalkState::Continue + }) + }); // Return the number of files traversed. Ok(files_scanned.load(Ordering::SeqCst)) From 64527b29a01799341c1aba740b1dfd5cb8adb0ef Mon Sep 17 00:00:00 2001 From: Stephan Boyer Date: Sat, 20 Jun 2026 00:55:16 -0700 Subject: [PATCH 2/2] Deduplicate walker root arguments --- src/main.rs | 51 +++++++++++++++++++++++---------------------------- src/walk.rs | 5 ++--- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/main.rs b/src/main.rs index e644055..4b61387 100644 --- a/src/main.rs +++ b/src/main.rs @@ -114,34 +114,29 @@ fn entry() -> Result<(), String> { let project_root = config.project_root; let ignore_rules = config.ignore_rules; let project_root_clone = project_root.clone(); - let files_scanned = walk::walk( - &project_root, - &project_root, - &ignore_rules, - move |file_path, file| { - // The `unwrap` is safe because the walker is rooted at `project_root_clone`. - let relative_file_path = file_path.strip_prefix(&project_root_clone).unwrap(); - let directives = directive::parse( - &tag_regex_clone, - &ref_regex_clone, - &file_regex_clone, - &dir_regex_clone, - relative_file_path, - BufReader::new(file), - ); - for tag in directives.tags { - tags_clone - .lock() - .unwrap() // Safe assuming no poisoning - .entry(tag.label.clone()) - .or_insert_with(Vec::new) - .push(tag.clone()); - } - refs_clone.lock().unwrap().extend(directives.refs); // Safe assuming no poisoning - files_clone.lock().unwrap().extend(directives.files); // Safe assuming no poisoning - dirs_clone.lock().unwrap().extend(directives.dirs); // Safe assuming no poisoning - }, - )?; + let files_scanned = walk::walk(&project_root, &ignore_rules, move |file_path, file| { + // The `unwrap` is safe because the walker is rooted at `project_root_clone`. + let relative_file_path = file_path.strip_prefix(&project_root_clone).unwrap(); + let directives = directive::parse( + &tag_regex_clone, + &ref_regex_clone, + &file_regex_clone, + &dir_regex_clone, + relative_file_path, + BufReader::new(file), + ); + for tag in directives.tags { + tags_clone + .lock() + .unwrap() // Safe assuming no poisoning + .entry(tag.label.clone()) + .or_insert_with(Vec::new) + .push(tag.clone()); + } + refs_clone.lock().unwrap().extend(directives.refs); // Safe assuming no poisoning + files_clone.lock().unwrap().extend(directives.files); // Safe assuming no poisoning + dirs_clone.lock().unwrap().extend(directives.dirs); // Safe assuming no poisoning + })?; // Decide what to do based on the subcommand. match cli.command.unwrap_or(Subcommand::Check) { diff --git a/src/walk.rs b/src/walk.rs index be96d89..f1b84d6 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -16,17 +16,16 @@ use std::{ // skips over symlinks. The number of files traversed is returned. pub fn walk( path: &Path, - current_dir: &Path, ignore_rules: &[String], callback: T, ) -> Result { // Keep track of the number of files traversed, and allow multiple threads to update it. let files_scanned = Arc::new(AtomicUsize::new(0)); - let overrides = build_overrides(current_dir, ignore_rules)?; + let overrides = build_overrides(path, ignore_rules)?; // Traverse the filesystem in parallel. WalkBuilder::new(path) - .current_dir(current_dir) + .current_dir(path) .hidden(false) .require_git(false) .parents(false)