1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
use crate::{Action, Data, Flag, Predicate, Rule, Scalar, SerializableRegex, Token}; use std::fs; use std::io; use std::path::{Path, PathBuf}; pub fn run(working_dir: impl AsRef<Path>, data: &Data) -> io::Result<()> { for dir_entry in fs::read_dir(working_dir)? { let dir_entry = dbg!(dir_entry?); if dir_entry.file_type()?.is_dir() { continue; } for rule in &data.rules { run_rule(dir_entry.path(), rule)?; } } Ok(()) } fn run_rule(path: impl AsRef<Path>, rule: &Rule) -> io::Result<()> { if path_matches_patterns(&path, rule.flags.contains(&Flag::IgnoreCase), &rule.patterns) { if let Some(predicate) = &rule.predicate { if file_matches_predicates(&path, predicate)? { return apply_action(&path, &rule.action); } } else { return apply_action(&path, &rule.action); } } Ok(()) } fn apply_action(path: impl AsRef<Path>, action: &Action) -> io::Result<()> { println!("apply_action({:?}, {:?})", path.as_ref(), action); match action { Action::Delete => fs::remove_file(path), Action::Move { to } => { fs::copy(&path, to.join(&path))?; fs::remove_file(&path) } } } fn path_matches_patterns( path: impl AsRef<Path>, ignore_case: bool, patterns: &[SerializableRegex], ) -> bool { if patterns.is_empty() { return true; } let path = if let Some(path) = path.as_ref().to_str() { path } else { return false; }; patterns.iter().map(|pat| pat.as_ref()).any(|pattern| { if ignore_case { pattern.is_match(&path.to_lowercase()) || pattern.is_match(&path.to_uppercase()) } else { pattern.is_match(path) } }) } fn file_matches_predicates(path: impl AsRef<Path>, predicate: &Predicate) -> io::Result<bool> { match predicate { Predicate::Comparison { token, operator, value, } => match (token, value) { (Token::Size, Scalar::Size(size)) => { let file_metadata = fs::metadata(path)?; Ok(operator.compare(&file_metadata.len(), size)) } (Token::Age, Scalar::Time(_)) => unimplemented!(), _ => Ok(false), }, } }