From e899cd2648fa18cf1ff7b54570b5ded362b0ee3b Mon Sep 17 00:00:00 2001 From: Cameron Cordes Date: Mon, 15 Feb 2021 18:06:53 -0500 Subject: [PATCH] Use depth first search for files --- src/main.rs | 53 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/main.rs b/src/main.rs index 53f0345..a76f13e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,11 @@ mod rack { matches: Vec, } + struct Traversal { + dirs: Vec, + entries: Vec, + } + impl Rack { pub fn new() -> Self { Rack { @@ -52,11 +57,12 @@ mod rack { dir: &PathBuf, gitignore_entries: Option>, ) -> io::Result<()> { - let entries = fs::read_dir(dir)?.collect::>>(); + let mut entries: Vec = fs::read_dir(dir)? + .filter_map(|e| e.ok()) + .collect::>(); let gitignore: Option<&DirEntry> = entries .iter() - .filter_map(|entry| entry.as_ref().ok()) .find(|entry| entry.path().file_name().unwrap() == ".gitignore"); let gitignore = match gitignore { @@ -70,8 +76,15 @@ mod rack { None => gitignore_entries.unwrap_or_default(), }; - for entry in entries { - let entry = entry?; + let mut initial = Vec::new(); + initial.append(&mut entries); + let mut traversal = Traversal { + dirs: initial, + entries: Vec::new(), + }; + + while !traversal.dirs.is_empty() { + let entry = traversal.dirs.pop().unwrap(); let file_type = entry.file_type()?; let path = entry.path(); let path = path.to_str().unwrap(); @@ -80,20 +93,26 @@ mod rack { continue; } - // TODO: Should borrow gitignore instead of cloning.. - self.traverse_dir(&entry.path(), Some(gitignore.clone()))?; + if let Ok(mut contents) = Rack::get_dir_entries(path) { + traversal.dirs.append(&mut contents); + } } else { if self.should_ignore(&gitignore, path, &entry) { continue; } - let result = self.check_file(&entry.path()); - match result { - Result::Ok(result) if !result.matches.is_empty() => self.matches.push(result), - _ => (), - } + + traversal.entries.push(entry); } } + let mut results = traversal + .entries + .iter() + .filter_map(|e| self.check_file(&e.path()).ok()) + .filter(|mat| mat.matches.len() > 0) + .collect::>(); + self.matches.append(&mut results); + Ok(()) } @@ -110,6 +129,14 @@ mod rack { false } + fn get_dir_entries(entry: &str) -> io::Result> { + let entries = fs::read_dir(entry)? + .filter_map(|e| e.ok()) + .collect::>(); + + Ok(entries) + } + fn check_file(&self, path: &Path) -> io::Result { let mut pattern = self.config.pattern.clone(); @@ -148,7 +175,9 @@ mod rack { }) } - fn print_report(&self) { + fn print_report(&mut self) { + self.matches + .sort_by(|l, r| l.file_name.partial_cmp(&r.file_name).unwrap()); for file in &self.matches { file.print(&self.config) }