hpk/src/db/mod.rs

92 lines
3.2 KiB
Rust

use std::fmt;
use {
crate::{Package, Repository, Version},
serde::{Deserialize, Serialize},
std::{collections::HashMap, error::Error},
url::Url,
};
#[derive(Clone, Debug)]
pub struct Update {
pub name: String,
pub version: Version,
pub release: u8,
pub url: Url,
}
impl fmt::Display for Update {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}-{}_{}", self.name, self.version, self.release)
}
}
impl Update {
pub fn full_url(&self) -> Result<Url, url::ParseError> {
self.url.join(&format!("{}.tar.zstd", self))
}
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Database {
pub packages: HashMap<String, Package>,
pub available: HashMap<String, Repository>,
}
impl Database {
pub fn update(&mut self) -> Result<(), Box<dyn Error>> {
unimplemented!();
}
pub fn add_package(&mut self, package: Package) {
let name = package.name.clone();
self.packages.insert(name, package);
}
pub fn remove_package(&mut self, name: &str) -> Option<Package> {
self.packages.remove(name)
}
pub fn get_upgradable(&mut self) -> Result<HashMap<String, Update>, Box<dyn Error>> {
self.update()?;
let mut updates = HashMap::<String, Update>::new();
for local_package in self.packages.values() {
let name = local_package.name.clone();
for repo in self.available.values() {
// Check if the remote has a package by this name
if let Some(remote_package) = repo.packages.get(&name) {
// Check if the remote package is an update
if remote_package.is_upgrade(&local_package) {
// Check if we've already pulled in an update from another repo,
// and if so compare versions
if let Some(other_update) = updates.get(&name) {
if remote_package.version > other_update.version {
// The remote version is an update to the already
// pulled in update, so swap it out
let update = Update {
name: name.clone(),
version: remote_package.version.clone(),
release: remote_package.release,
url: repo.base_url.clone(),
};
updates.insert(name.clone(), update);
}
} else {
// First time we've seen this update, so insert it
// into our hashmap
let update = Update {
name: name.clone(),
version: remote_package.version.clone(),
release: remote_package.release,
url: repo.base_url.clone(),
};
updates.insert(name.clone(), update);
}
}
}
}
}
Ok(updates)
}
}