use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
use crate::paths;
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct Registry {
#[serde(default)]
pub projects: Vec<Project>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Project {
pub name: String,
pub path: PathBuf,
pub template: String,
pub created_at: String,
}
impl Registry {
pub fn load() -> Result<Self> {
let path = paths::registry_file()?;
if !path.exists() {
return Ok(Registry::default());
}
let text = fs::read_to_string(&path)
.with_context(|| format!("Failed to read {}", path.display()))?;
let reg: Registry =
toml::from_str(&text).with_context(|| format!("Failed to parse {}", path.display()))?;
Ok(reg)
}
pub fn save(&self) -> Result<()> {
let path = paths::registry_file()?;
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let text = toml::to_string_pretty(self)?;
fs::write(&path, text)?;
Ok(())
}
pub fn add(&mut self, project: Project) {
if let Some(slot) = self.projects.iter_mut().find(|p| p.name == project.name) {
*slot = project;
} else {
self.projects.push(project);
}
}
pub fn remove(&mut self, name: &str) -> bool {
let before = self.projects.len();
self.projects.retain(|p| p.name != name);
before != self.projects.len()
}
#[allow(dead_code)]
pub fn find(&self, name: &str) -> Option<&Project> {
self.projects.iter().find(|p| p.name == name)
}
}