Add Update and Database types and begin forming infra for updating

packages
This commit is contained in:
Nathan Fisher 2023-03-25 17:59:53 -04:00
parent 9d53c9f44d
commit 6c62f15a41
3 changed files with 93 additions and 3 deletions

64
src/db/mod.rs Normal file
View File

@ -0,0 +1,64 @@
use {
crate::{Repository, Package, Version},
serde::{Deserialize, Serialize},
std::{collections::HashMap, error::Error},
url::Url,
};
pub struct Update {
pub name: String,
pub version: Version,
pub url: Url,
}
#[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 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,
url: repo.base_url.clone(),
};
updates.insert(name, 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,
url: repo.base_url,
};
updates.insert(name, update);
}
}
}
}
}
Ok(updates)
}
}

View File

@ -1,4 +1,5 @@
#![warn(clippy::all, clippy::pedantic)]
mod db;
mod hooks;
mod item;
mod package;
@ -7,9 +8,10 @@ mod repository;
mod version;
pub use {
db: Database,
hooks::Hooks,
item::Item,
package::{create as create_package, Dependency, Package, Specs},
package::{create_package, Dependency, Package, Specs},
plist::*,
repository::Repository,
tar,

View File

@ -37,6 +37,7 @@ pub struct Group {
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
/// the metadata associated with a package
pub struct Package {
/// The name of the package minus all version information
pub name: String,
@ -91,7 +92,7 @@ impl Package {
to_string_pretty(self, cfg)
}
pub fn save_ron_and_create_tar_node(&self, outdir: &Path) -> Result<Node, Box<dyn Error>> {
fn save_ron_and_create_tar_node(&self, outdir: &Path) -> Result<Node, Box<dyn Error>> {
if !outdir.exists() {
fs::create_dir_all(outdir)?;
}
@ -112,12 +113,35 @@ impl Package {
Ok(node)
}
/// Returns the formatted full package name including version and release strings
pub fn fullname(&self) -> String {
format!("{}-{}_{}", self.name, self.version, self.release)
}
/// Tests whether this package is an update for another
pub fn is_upgrade(&self, other: &Self) -> bool {
self.name == other.name && self.version > other.version
}
}
pub fn create(path: &Path, specs: Specs, outdir: &Path) -> Result<(), Box<dyn Error>> {
/// Creates a package archive given a path to the included files, a package `Specs`
/// file and an output directory
///
/// ## Usage
/// ```
/// use std::path::Path;
/// use hpk::Specs;
///
/// let staging = Path::new("staged");
/// let outdir = Path::new("package");
/// let specs = Specs {
/// name: "foo".to_string(),
/// version: "0.42.0".parse().unwrap(),
/// description: "an example package".to_string(),
/// ..Default::default()
/// };
/// let result = hpk::create_package(&staging, specs, &outdir);
pub fn create_package(path: &Path, specs: Specs, outdir: &Path) -> Result<(), Box<dyn Error>> {
if !outdir.exists() {
fs::create_dir_all(outdir)?;
}