use crate::error::Error;
use crate::project::manifest::Environment;
use crate::registry::index::DownloadSource;
use serde::{Deserialize, Serialize};
use std::path::Path;
pub const LOCKFILE: &str = "lpm.lock";
#[derive(Serialize, Deserialize, Debug)]
pub struct Lockfile {
pub version: u32,
#[serde(default, rename = "package")]
pub packages: Vec<LockedPackage>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct LockedPackage {
pub name: String,
pub version: String,
pub environment: Environment,
pub link: String,
pub index: String,
#[serde(flatten)]
pub source: DownloadSource,
}
impl Lockfile {
pub fn new(packages: Vec<LockedPackage>) -> Self {
Lockfile {
version: 1,
packages,
}
}
pub fn load() -> Result<Self, Error> {
let path = Path::new(LOCKFILE);
if !path.exists() {
return Err(Error::LockfileMissing);
}
Ok(toml::from_str(&std::fs::read_to_string(path)?)?)
}
pub fn save(&self) -> Result<(), Error> {
let header = "# This file is generated by `lpm install`; do not edit it manually.\n";
let body = toml::to_string(self).expect("lockfile serializes");
std::fs::write(LOCKFILE, format!("{header}{body}"))?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips() {
let lockfile = Lockfile::new(vec![
LockedPackage {
name: "evaera/promise".to_string(),
version: "4.0.0".to_string(),
environment: Environment::Shared,
link: "Promise".to_string(),
index: "https://github.com/UpliftGames/wally-index".to_string(),
source: DownloadSource::Zip {
url: "https://api.wally.run/v1/package-contents/evaera/promise/4.0.0"
.to_string(),
},
},
LockedPackage {
name: "pesde/hello".to_string(),
version: "1.0.2".to_string(),
environment: Environment::Luau,
link: "hello".to_string(),
index: "https://github.com/pesde-pkg/index".to_string(),
source: DownloadSource::TarGz {
url: "https://registry.pesde.daimond113.com/v1/packages/pesde%2Fhello/1.0.2/luau/archive".to_string(),
},
},
]);
let text = toml::to_string(&lockfile).unwrap();
let parsed: Lockfile = toml::from_str(&text).unwrap();
assert_eq!(parsed.version, 1);
assert_eq!(parsed.packages.len(), 2);
assert_eq!(parsed.packages[0].name, "evaera/promise");
assert!(matches!(
&parsed.packages[1].source,
DownloadSource::TarGz { url } if url.contains("pesde%2Fhello")
));
}
}