use std::{fs, path::PathBuf};
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use crate::spec::ReleaseId;
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq, Eq)]
pub struct CurrentRelease {
pub channel: String,
pub version: String,
}
impl From<&ReleaseId> for CurrentRelease {
fn from(id: &ReleaseId) -> Self {
Self {
channel: id.channel.as_str().to_owned(),
version: id.version.clone(),
}
}
}
impl PartialEq<ReleaseId> for CurrentRelease {
fn eq(&self, other: &ReleaseId) -> bool {
self.channel == other.channel.as_str() && self.version == other.version
}
}
impl PartialEq<CurrentRelease> for ReleaseId {
fn eq(&self, other: &CurrentRelease) -> bool {
other == self
}
}
pub struct CurrentManager {
path: PathBuf,
}
impl CurrentManager {
pub fn new(path: PathBuf) -> Self {
Self { path }
}
pub fn load(&self) -> Result<Option<CurrentRelease>> {
if !self.path.exists() {
return Ok(None);
}
let data = fs::read(&self.path).with_context(|| {
format!("failed to read current release at {}", self.path.display())
})?;
let parsed = serde_json::from_slice(&data).with_context(|| {
format!(
"failed to parse current release JSON at {}",
self.path.display()
)
})?;
Ok(Some(parsed))
}
pub fn save(&self, id: &ReleaseId) -> Result<()> {
let current: CurrentRelease = id.into();
let data = serde_json::to_vec_pretty(¤t)?;
fs::write(&self.path, data).with_context(|| {
format!(
"failed to persist current release at {}",
self.path.display()
)
})
}
pub fn clear(&self) -> Result<()> {
if self.path.exists() {
fs::remove_file(&self.path).with_context(|| {
format!(
"failed to remove current release file at {}",
self.path.display()
)
})?;
}
Ok(())
}
}