diff --git a/src/lib.rs b/src/lib.rs index 6cbbddc..151bd1b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ use std::{ env, fs, io::{self, Write, Error, ErrorKind}, - path::PathBuf, + path::{Path, PathBuf}, process::Command, }; @@ -57,6 +57,63 @@ pub fn get_absolute_path(path: &str) -> Option { fs::canonicalize(path).ok() } +pub fn walk_dir(dir: &Path, + func_walk_error: &FError, + func_process_file: &FProcess, + func_filter_dir: &FFilter) -> XResult<()> + where FError: Fn(&Path, Box) -> (), + FProcess: Fn(&Path) -> (), + FFilter: Fn(&Path) -> bool { + walk_dir_with_depth_check(&mut 0u32, dir, func_walk_error, func_process_file, func_filter_dir) +} + +fn walk_dir_with_depth_check(depth: &mut u32, dir: &Path, + func_walk_error: &FError, + func_process_file: &FProcess, + func_filter_dir: &FFilter) -> XResult<()> + where FError: Fn(&Path, Box) -> (), + FProcess: Fn(&Path) -> (), + FFilter: Fn(&Path) -> bool { + if *depth > 100u32 { + return Err(new_box_error(&format!("Depth exceed, depth: {}, path: {:?}", *depth, dir))); + } + let read_dir = match dir.read_dir() { + Err(err) => { + func_walk_error(&dir, Box::new(err)); + return Ok(()); + }, + Ok(rd) => rd, + }; + for dir_entry_item in read_dir { + let dir_entry = match dir_entry_item { + Err(err) => { + func_walk_error(&dir, Box::new(err)); + continue; // Ok? + }, + Ok(item) => item, + }; + + let path_buf = dir_entry.path(); + let sub_dir = path_buf.as_path(); + if sub_dir.is_file() { + func_process_file(&sub_dir); + } else if sub_dir.is_dir() { + if func_filter_dir(&sub_dir) { + *depth += 1; + match walk_dir_with_depth_check(depth, &sub_dir, func_walk_error, func_process_file, func_filter_dir) { + Err(err) => { + func_walk_error(&sub_dir, err); + () + }, + Ok(_) => (), + } + *depth -= 1; + } + } // should process else ? not file, dir + } + Ok(()) +} + pub fn new_box_error(m: &str) -> Box { Box::new(Error::new(ErrorKind::Other, m)) }