diskr-cli 1.0.0

Save your disk space, without fear of deleting the wrong thing.
Documentation
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    pub min_file_size_mb: u64,
    pub stale_days: i64,
    pub stale_min_size_mb: u64,
    pub exclude_paths: Vec<String>,
    pub watch_duration_hours: u64,
    pub duplicate_min_size_kb: u64,
    pub cross_filesystems: bool,
    pub use_trash: bool,
}

impl Default for Config {
    fn default() -> Self {
        Self {
            min_file_size_mb: 100,
            stale_days: 180,
            stale_min_size_mb: 50,
            exclude_paths: vec!["/proc".into(), "/sys".into(), "/dev".into()],
            watch_duration_hours: 24,
            duplicate_min_size_kb: 4,
            cross_filesystems: false,
            use_trash: true,
        }
    }
}

pub fn config_path() -> Result<PathBuf> {
    let base = dirs::config_dir().context("no config dir")?;
    Ok(base.join("diskr").join("config.toml"))
}

pub fn load() -> Result<Config> {
    let path = config_path()?;
    if !path.exists() {
        let cfg = Config::default();
        save(&cfg)?;
        return Ok(cfg);
    }
    let text = fs::read_to_string(&path)?;
    Ok(toml::from_str(&text).unwrap_or_default())
}

pub fn save(cfg: &Config) -> Result<()> {
    let path = config_path()?;
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    let text = toml::to_string_pretty(cfg)?;
    fs::write(path, text)?;
    Ok(())
}