use std::path::Path; use std::fs; use std::os::unix::fs::MetadataExt; use glob::Pattern; pub fn trim_handler(repo: &String, trim_date: i64) { let etc_path = super::get_aeropkg_etc(); let cfg_path = etc_path.join("aeropkg.md"); let rules = &crate::utils::parser::get_trim_rules(&cfg_path).unwrap(); let pkg_dir = &super::get_aeropkg_base().join(repo); trim(repo, pkg_dir, trim_date, rules) } fn trim(repo: &String, path: &Path, trim_date: i64, rules: &String) { let metadata = fs::symlink_metadata(path).unwrap(); if metadata.is_dir() { if rules_check(repo, path, rules) { for entry in fs::read_dir(path).unwrap() { let entry_path = &entry.unwrap().path(); trim(repo, entry_path, trim_date, rules) } } } else if metadata.is_file() { if rules_check(repo, path, rules) { let atime = metadata.atime(); if atime < trim_date { if let Err(e) = fs::remove_file(path) { panic!("Failed to remove file: {}", e) } } } } else if metadata.file_type().is_symlink() { if let Ok(symlink_value) = fs::read_link(path) { let symlink_path = if symlink_value.is_relative() { path.parent().unwrap().join(&symlink_value) } else { symlink_value }; if !symlink_path.exists() { println!("remove symlink: {} {}", path.display(), symlink_path.display()); fs::remove_file(path).unwrap(); } } } } fn rules_check(repo: &String, path: &Path, rules: &String) -> bool { let mut confirm = true; for rule in rules.lines() { let mut rule = rule.trim(); let invert = rule.starts_with('!'); if invert { rule = &rule[1..]; } let wildcard_string = if rule.starts_with('/') { &rule.to_string() } else { &super::get_aeropkg_base().join(repo).join(rule).to_string_lossy().into_owned() }; let path_str = path.to_str().unwrap_or(""); if let Ok(pattern) = Pattern::new(wildcard_string) { if pattern.matches(path_str) { confirm = !invert } } } confirm }