You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nenv/src/repository/local_versions.rs

109 lines
3.2 KiB
Rust

use std::{fs::File, io::Write};
use semver::VersionReq;
use serde::{Deserialize, Serialize};
use crate::{
consts::INSTALLED_VERSION_FILE,
versioning::{SimpleVersion, VersionMetadata},
};
use miette::{Context, IntoDiagnostic, Result};
#[derive(Serialize, Deserialize, Default)]
pub struct InstalledVersions {
ordered_versions: Vec<(SimpleVersion, VersionMetadata)>,
}
impl InstalledVersions {
pub fn new(mut versions: Vec<(SimpleVersion, VersionMetadata)>) -> Self {
versions.sort_by_key(|e| e.0);
versions.dedup_by_key(|e| e.0);
Self {
ordered_versions: versions,
}
}
/// Loads the local versions
pub fn load() -> Result<Self> {
let reader = File::open(&*INSTALLED_VERSION_FILE)
.into_diagnostic()
.context("Opening local versions file")?;
let versions = bincode::deserialize_from(reader)
.into_diagnostic()
.context("Deserializing local versions")?;
Ok(versions)
}
/// Saves the local versions
pub fn save(&self) -> Result<()> {
let mut file = File::create(&*INSTALLED_VERSION_FILE)
.into_diagnostic()
.context("Opening local versions file")?;
bincode::serialize_into(&mut file, &self)
.into_diagnostic()
.context("Serializing local versions")?;
file.flush()
.into_diagnostic()
.context("Flushing local versions to file")?;
Ok(())
}
/// Inserts a new version. This requires reordering the list
pub fn insert(&mut self, version: (SimpleVersion, VersionMetadata)) {
self.ordered_versions.push(version);
self.ordered_versions.sort_by_key(|e| e.0);
self.ordered_versions.dedup_by_key(|e| e.0);
}
/// Removes a version. This keeps the order intact
pub fn remove(&mut self, version: &SimpleVersion) {
self.ordered_versions.retain(|(v, _)| v != version)
}
pub fn all(&self) -> Vec<&SimpleVersion> {
self.ordered_versions.iter().map(|(v, _)| v).collect()
}
pub fn latest(&self) -> Option<&VersionMetadata> {
self.ordered_versions.last().map(|(_, m)| m)
}
pub fn latest_lts(&self) -> Option<&VersionMetadata> {
self.ordered_versions
.iter()
.filter(|(_, m)| m.lts.is_some())
.last()
.map(|(_, m)| m)
}
pub fn lts<S: AsRef<str>>(&self, lts: S) -> Option<&VersionMetadata> {
self.ordered_versions
.iter()
.filter_map(|(v, m)| Some((v, m.lts.clone()?, m)))
.filter(|(_, n, _)| n == lts.as_ref())
.last()
.map(|(_, _, m)| m)
}
pub fn fulfilling(&self, req: &VersionReq) -> Option<&VersionMetadata> {
self.ordered_versions
.iter()
.filter(|(v, _)| req.matches(&v.to_owned().into()))
.last()
.map(|(_, m)| m)
}
}
impl From<Vec<VersionMetadata>> for InstalledVersions {
fn from(versions: Vec<VersionMetadata>) -> Self {
let versions = versions
.into_iter()
.map(|v| (v.version.to_owned(), v))
.collect::<Vec<_>>();
Self::new(versions)
}
}