diskr/analyzer/
patterns.rs1use crate::scanner::{walker::age_days, FsNode};
2use once_cell::sync::Lazy;
3use serde::Serialize;
4use std::path::PathBuf;
5
6static CACHE_DIR_NAMES: Lazy<Vec<&'static str>> = Lazy::new(|| vec![
7 "node_modules", "target", "__pycache__", ".cache", "vendor", "dist", "build",
8 ".venv", "venv", ".tox", ".pytest_cache", ".gradle", ".m2", "Pods", ".next",
9 ".nuxt", "coverage", ".parcel-cache",
10]);
11
12const INSTALLED_PACKAGE_FRAGMENTS: &[&str] = &[
13 "/gems/",
14 "/.gem/",
15 "/vendor/bundle/",
16 "/site-packages/",
17 "/.cargo/registry/",
18];
19
20fn is_inside_installed_package(path: &std::path::Path) -> bool {
21 let s = path.to_string_lossy();
22 INSTALLED_PACKAGE_FRAGMENTS.iter().any(|f| s.contains(f))
23}
24
25#[derive(Debug, Clone, Serialize)]
26pub struct CacheDir {
27 pub path: PathBuf,
28 pub kind: String,
29 pub size: u64,
30 pub age_days: i64,
31}
32
33pub fn find_dev_caches(node: &FsNode, out: &mut Vec<CacheDir>) {
34 if !node.is_dir { return; }
35 let name = node.path.file_name().and_then(|n| n.to_str()).unwrap_or("");
36 if CACHE_DIR_NAMES.contains(&name) && !is_inside_installed_package(&node.path) {
37 let age = node.modified.map(age_days).unwrap_or(0);
38 out.push(CacheDir { path: node.path.clone(), kind: name.to_string(), size: node.size, age_days: age });
39 return;
40 }
41 for c in &node.children {
42 find_dev_caches(c, out);
43 }
44}