deepwash 1.4.0

A Command Line Interface to clean your machine (docker...)
Documentation
use crate::tasks::clean::is_target;
use std::fs;
use std::path::{Path, PathBuf};

pub struct Match {
    pub path: PathBuf,
    pub size: u64,
    pub kind: String,
}

pub fn dir_size(path: &Path) -> u64 {
    let mut total = 0;
    let entries = match fs::read_dir(path) {
        Ok(e) => e,
        Err(_) => return 0,
    };
    for entry in entries.flatten() {
        let meta = match entry.path().symlink_metadata() {
            Ok(m) => m,
            Err(_) => continue,
        };
        if meta.file_type().is_symlink() {
            continue;
        }
        if meta.is_dir() {
            total += dir_size(&entry.path());
        } else {
            total += meta.len();
        }
    }
    total
}

pub fn scan(root: &Path, names: &[String]) -> Vec<Match> {
    let mut matches = Vec::new();
    walk(root, names, &mut matches);
    matches
}

fn walk(dir: &Path, names: &[String], matches: &mut Vec<Match>) {
    let entries = match fs::read_dir(dir) {
        Ok(e) => e,
        Err(_) => return,
    };
    for entry in entries.flatten() {
        let path = entry.path();
        let meta = match path.symlink_metadata() {
            Ok(m) => m,
            Err(_) => continue,
        };
        if meta.file_type().is_symlink() || !meta.is_dir() {
            continue;
        }
        let name = match path.file_name().and_then(|n| n.to_str()) {
            Some(n) => n.to_string(),
            None => continue,
        };
        if is_target(&name, names) {
            matches.push(Match {
                size: dir_size(&path),
                kind: name,
                path,
            });
        } else {
            walk(&path, names, matches);
        }
    }
}