use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct State {
pub links: Vec<PathBuf>,
#[serde(default)]
pub backups: Vec<Backup>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Backup {
pub dest: PathBuf,
pub kept_at: PathBuf,
}
impl State {
pub fn path(home: &Path) -> PathBuf {
home.join(".local/state/sennit/state.json")
}
pub fn load(home: &Path) -> Result<Self> {
let p = Self::path(home);
match std::fs::read_to_string(&p) {
Ok(text) => serde_json::from_str(&text)
.with_context(|| format!("failed to parse {}", p.display())),
Err(_) => Ok(Self::default()),
}
}
pub fn save(&self, home: &Path) -> Result<()> {
let p = Self::path(home);
if let Some(parent) = p.parent() {
std::fs::create_dir_all(parent)?;
}
let text = serde_json::to_string_pretty(self)?;
std::fs::write(&p, text).with_context(|| format!("failed to write {}", p.display()))
}
pub fn stale(&self, current: &[PathBuf]) -> Vec<PathBuf> {
self.links
.iter()
.filter(|old| !current.contains(old))
.cloned()
.collect()
}
}