diskr-cli 1.0.0

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

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CleanEvent {
    pub timestamp: DateTime<Utc>,
    pub paths: Vec<PathBuf>,
    pub bytes_freed: u64,
    pub note: String,
}

#[derive(Debug, Default, Serialize, Deserialize)]
pub struct History {
    pub events: Vec<CleanEvent>,
}

fn history_path() -> Result<PathBuf> {
    let base = dirs::data_local_dir().context("no local data dir")?;
    Ok(base.join("diskr").join("history.json"))
}

pub fn load() -> Result<History> {
    let path = history_path()?;
    if !path.exists() {
        return Ok(History::default());
    }
    let text = fs::read_to_string(&path)?;
    Ok(serde_json::from_str(&text).unwrap_or_default())
}

pub fn append(event: CleanEvent) -> Result<()> {
    let path = history_path()?;
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    let mut history = load()?;
    history.events.push(event);
    save(&path, &history)
}

pub fn last_event() -> Result<Option<CleanEvent>> {
    Ok(load()?.events.last().cloned())
}

fn save(path: &Path, history: &History) -> Result<()> {
    let text = serde_json::to_string_pretty(history)?;
    fs::write(path, text)?;
    Ok(())
}