use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct RivoxLockfile {
pub version: u32,
pub created_at: String,
#[serde(default)]
pub ecosystems: Vec<LockedEcosystem>,
#[serde(default)]
pub cross_refs: Vec<LockedCrossRef>,
#[serde(default)]
pub graph_nodes: Vec<LockedGraphNode>,
pub provenance: Option<LockedProvenance>,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct LockedEcosystem {
pub name: String,
pub tool: String,
pub tool_version: String,
pub lockfile_path: String,
pub lockfile_hash: String,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct LockedCrossRef {
pub from: String,
pub to: String,
pub hash: String,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct LockedGraphNode {
pub ecosystem: String,
pub package: String,
pub version: String,
pub content_hash: String,
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct LockedProvenance {
pub bundle_path: String,
pub signature_ref: String,
}
impl RivoxLockfile {
pub fn load_from_file(path: &Path) -> Result<Self> {
let content = fs::read_to_string(path)
.with_context(|| format!("Failed to read lockfile at {}", path.display()))?;
let lockfile: RivoxLockfile = toml::from_str(&content)
.with_context(|| format!("Failed to parse TOML lockfile at {}", path.display()))?;
Ok(lockfile)
}
pub fn save_to_file(&self, path: &Path) -> Result<()> {
let content =
toml::to_string_pretty(self).context("Failed to serialize rivox.lock TOML")?;
fs::write(path, content)
.with_context(|| format!("Failed to write lockfile to {}", path.display()))?;
Ok(())
}
}