use crate::scanner::{walker::age_days, FsNode};
use once_cell::sync::Lazy;
use serde::Serialize;
use std::path::PathBuf;
static CACHE_DIR_NAMES: Lazy<Vec<&'static str>> = Lazy::new(|| vec![
"node_modules", "target", "__pycache__", ".cache", "vendor", "dist", "build",
".venv", "venv", ".tox", ".pytest_cache", ".gradle", ".m2", "Pods", ".next",
".nuxt", "coverage", ".parcel-cache",
]);
const INSTALLED_PACKAGE_FRAGMENTS: &[&str] = &[
"/gems/",
"/.gem/",
"/vendor/bundle/",
"/site-packages/",
"/.cargo/registry/",
];
fn is_inside_installed_package(path: &std::path::Path) -> bool {
let s = path.to_string_lossy();
INSTALLED_PACKAGE_FRAGMENTS.iter().any(|f| s.contains(f))
}
#[derive(Debug, Clone, Serialize)]
pub struct CacheDir {
pub path: PathBuf,
pub kind: String,
pub size: u64,
pub age_days: i64,
}
pub fn find_dev_caches(node: &FsNode, out: &mut Vec<CacheDir>) {
if !node.is_dir { return; }
let name = node.path.file_name().and_then(|n| n.to_str()).unwrap_or("");
if CACHE_DIR_NAMES.contains(&name) && !is_inside_installed_package(&node.path) {
let age = node.modified.map(age_days).unwrap_or(0);
out.push(CacheDir { path: node.path.clone(), kind: name.to_string(), size: node.size, age_days: age });
return;
}
for c in &node.children {
find_dev_caches(c, out);
}
}