use std::path::Path;
use std::{
fs::read_to_string,
io::{self, BufWriter, Write},
};
use fs_err::File;
use semver::Version;
use serde::{Deserialize, Serialize};
use crate::{
manifest::Manifest, package_id::PackageId, package_name::PackageName, resolution::Resolve,
};
pub const LOCKFILE_NAME: &str = "wally.lock";
#[derive(Debug, Serialize, Deserialize)]
pub struct Lockfile {
pub registry: String,
#[serde(rename = "package")]
pub packages: Vec<LockPackage>,
}
impl Lockfile {
pub fn from_manifest(manifest: &Manifest) -> Self {
Self {
registry: manifest.package.registry.clone(),
packages: Vec::new(),
}
}
pub fn from_resolve(resolve: &Resolve) -> Self {
let mut packages = Vec::new();
for package_id in &resolve.activated {
let dependencies = resolve
.shared_dependencies
.get(package_id)
.map(|dependencies| {
dependencies
.iter()
.map(|(key, value)| (key.clone(), value.clone()))
.collect()
})
.unwrap_or_else(Vec::new);
packages.push(LockPackage::Registry(RegistryLockPackage {
name: package_id.name().clone(),
version: package_id.version().clone(),
checksum: None,
dependencies,
}));
}
Self {
registry: "test".to_owned(),
packages,
}
}
pub fn load(project_path: &Path) -> anyhow::Result<Option<Self>> {
let lockfile_path = project_path.join(LOCKFILE_NAME);
let contents = match read_to_string(&lockfile_path) {
Ok(contents) => contents,
Err(err) => {
if err.kind() == io::ErrorKind::NotFound {
return Ok(None);
} else {
return Err(err.into());
}
}
};
Ok(Some(toml::from_str(&contents)?))
}
pub fn save(&self, project_path: &Path) -> anyhow::Result<()> {
let lockfile_path = project_path.join(LOCKFILE_NAME);
let serialized = toml::to_string(self)?;
let mut file = BufWriter::new(File::create(lockfile_path)?);
writeln!(file, "# This file is automatically @generated by Wally.")?;
writeln!(file, "# It is not intended for manual editing.")?;
write!(file, "{}", serialized)?;
file.flush()?;
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum LockPackage {
Registry(RegistryLockPackage),
Git(GitLockPackage),
}
#[derive(Debug, Serialize, Deserialize)]
pub struct RegistryLockPackage {
pub name: PackageName,
pub version: Version,
pub checksum: Option<String>,
#[serde(default)]
pub dependencies: Vec<(String, PackageId)>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct GitLockPackage {
pub name: String,
pub rev: String,
pub commit: String,
#[serde(default)]
pub dependencies: Vec<PackageId>,
}