diskr-cli 1.0.0

Save your disk space, without fear of deleting the wrong thing.
Documentation
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);
    }
}