feat: implement packagequeue
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/tag/woodpecker Pipeline was successful

This commit is contained in:
Didier Slof 2023-08-13 20:53:58 +02:00
parent 2ca231e761
commit 80c3072174
Signed by: didier
GPG key ID: 01E71F18AA4398E5
10 changed files with 176 additions and 60 deletions

View file

@ -8,3 +8,13 @@ pub struct Build {
pub install_script: String, pub install_script: String,
pub dependencies: HashMap<String, String>, pub dependencies: HashMap<String, String>,
} }
impl Default for Build {
fn default() -> Self {
Build {
dependencies: HashMap::default(),
build_script: String::default(),
install_script: String::default()
}
}
}

View file

@ -3,7 +3,7 @@ use std::fmt::{Display, Formatter};
use std::io; use std::io;
use std::path::Path; use std::path::Path;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct PKGFile { pub struct PKGFile {
pub manifest: String, pub manifest: String,
pub data: Vec<u8>, pub data: Vec<u8>,

View file

@ -44,7 +44,6 @@ build_script = "scripts/build" # relative to pkg
install_script = "scripts/install" # relative to pkg install_script = "scripts/install" # relative to pkg
[build.dependencies] [build.dependencies]
base = "latest,stable" # selected by default
## pkgr.* ## pkgr.*
# packager is the official client but you may use other clients supporting the "pkgr v1 spec". # packager is the official client but you may use other clients supporting the "pkgr v1 spec".

27
pkgr/src/api/mod.rs Normal file
View file

@ -0,0 +1,27 @@
use reqwest::blocking::Response;
pub struct APITransaction<R = Response> {
/// Query made to API.
query: String, //TODO: enum
/// Response struct from abstracted library
_response: Option<R>
}
impl<R> APITransaction<R> {
pub fn new(_response: Option<R>) -> Self {
APITransaction {
query: String::default(),
_response
}
}
}
pub struct API {
base_url: String,
token: Option<String>,
history: Vec<APITransaction>
}
impl API {
}

View file

@ -8,6 +8,7 @@ use manifest::package::PackageType;
use crate::CONFIG; use crate::CONFIG;
use crate::package::identifier::PackageIdentifier; use crate::package::identifier::PackageIdentifier;
use crate::package::Package; use crate::package::Package;
use crate::package::queue::PackageQueue;
use crate::process::Process; use crate::process::Process;
use crate::types::fetch::TryFetch; use crate::types::fetch::TryFetch;
@ -76,14 +77,10 @@ impl Command {
exit(1); exit(1);
} }
trace!("Starting install..."); let mut queue = PackageQueue::new();
match pkg.install(CONFIG.with(|c| if !*build { c.build_by_default } else { *build })) { queue.add_package(pkg, *build);
Ok(_) => (), trace!("Installing queue...");
Err(e) => { queue.install(*build);
error!("Install failed: {}", e.to_string());
exit(1);
}
}
let end = std::time::Instant::now(); let end = std::time::Instant::now();
let _unix_end = std::time::SystemTime::now() let _unix_end = std::time::SystemTime::now()
@ -117,6 +114,7 @@ impl Command {
} => { } => {
if let Some(p) = package_identifier { if let Some(p) = package_identifier {
if let Ok(mut pkg) = Package::try_fetch(p.clone()) { if let Ok(mut pkg) = Package::try_fetch(p.clone()) {
trace!("{}", pkg.pkgfile.manifest);
info!(target: "item", "Identifier: {:?}", pkg.identifier); info!(target: "item", "Identifier: {:?}", pkg.identifier);
info!(target: "item", ""); info!(target: "item", "");
let mani = pkg.manifest(); let mani = pkg.manifest();
@ -134,6 +132,34 @@ impl Command {
types.join(", ") types.join(", ")
}); });
info!(target: "item", ""); info!(target: "item", "");
info!(target: "item", "Dependencies: {}", {
let deps = pkg.dependencies();
if deps.len() == 0 {
String::from("None")
} else {
deps
.iter()
.map(|p| {
p.identifier.to_string()
})
.collect::<Vec<String>>()
.join(", ")
}
});
info!(target: "item", "Build Dependencies: {}", {
let deps = pkg.build_dependencies();
if deps.len() == 0 {
String::from("None")
} else {
deps
.iter()
.map(|p| {
p.identifier.to_string()
})
.collect::<Vec<String>>()
.join(", ")
}
});
} else { } else {
error!("Could not find {p}"); error!("Could not find {p}");
} }

View file

@ -19,6 +19,7 @@ mod config;
mod types; mod types;
/// utils /// utils
mod util; mod util;
mod api;
thread_local! { thread_local! {
static CONFIG: config::Config = config::Config::from_path("/etc/pkgr.toml") static CONFIG: config::Config = config::Config::from_path("/etc/pkgr.toml")

View file

@ -24,11 +24,11 @@ impl std::fmt::Display for PackageIdentifierError {
impl Error for PackageIdentifierError {} impl Error for PackageIdentifierError {}
#[derive(Clone)] #[derive(Clone, Eq, PartialEq)]
pub enum PackageIdentifier { pub enum PackageIdentifier {
PackageLocator(PackageLocator), PackageLocator(PackageLocator),
URI(String), URI(String),
Path(String), Path(String)
} }
impl std::fmt::Debug for PackageIdentifier { impl std::fmt::Debug for PackageIdentifier {
@ -59,7 +59,7 @@ impl std::fmt::Display for PackageIdentifier {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct PackageLocator { pub struct PackageLocator {
pub name: String, pub name: String,
pub version: Option<u32>, pub version: Option<u32>,
@ -160,8 +160,9 @@ impl FromStr for PackageLocator {
} }
} }
impl From<(String, String)> for PackageLocator { impl TryFrom<(String, String)> for PackageLocator {
fn from((name, locate_str): (String, String)) -> Self { type Error = PackageIdentifierError;
fn try_from((name, locate_str): (String, String)) -> Result<PackageLocator, Self::Error> {
// name = "pkg" // name = "pkg"
// locate_str = "1.0.0:tag1,tag2" or "1.0.0" or "tag1,tag2" // locate_str = "1.0.0:tag1,tag2" or "1.0.0" or "tag1,tag2"
let mut version = None; let mut version = None;
@ -185,10 +186,10 @@ impl From<(String, String)> for PackageLocator {
); );
} }
PackageLocator { Ok(PackageLocator {
name, name,
version, version,
tags, tags,
} })
} }
} }

View file

@ -68,25 +68,6 @@ impl PackageInstaller {
return Err(e); return Err(e);
} }
debug!("extracted package in: {}", tmpdir.to_string()); debug!("extracted package in: {}", tmpdir.to_string());
{
let mut tmpdir = tmpdir.clone();
tmpdir.push(&self.manifest.bin.clone().unwrap().root);
if prompt_bool("See all pending installation files?", true) {
if let Err(e) = visit_dirs(tmpdir.path().as_path(),
&|d| {
info!(target: "item", "{}", d.path()
.to_str()
.unwrap()
.replace(&tmpdir.to_string(), ""))
})
{
error!("Could not show files: {}", e);
}
}
}
if !prompt_bool("Continue?", is_noninteractive()) {
return Err(BinError::Cancelled);
}
match self.apply_overlay() { match self.apply_overlay() {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(e) => Err(BinError::IOError(e)) Err(e) => Err(BinError::IOError(e))
@ -109,25 +90,6 @@ impl PackageInstaller {
} }
let build_manifest = self.manifest.build.clone().unwrap(); let build_manifest = self.manifest.build.clone().unwrap();
// TODO: Check dependencies // TODO: Check dependencies
for pkg_tuple in build_manifest.dependencies {
let mut pkg = Package::try_fetch(
PackageIdentifier::PackageLocator(
PackageLocator::from(pkg_tuple)
)
).expect("no pkg");
if !pkg.is_installed() {
match pkg.install(CONFIG.with(|c| {
c.build_by_default
})) {
Ok(_) => { info!("Installed dependency: \"{}\"", pkg.manifest().package.name) }
Err(_) => {
error!("Could not install dependency: \"{}\"", pkg.identifier);
exit(1);
}
}
}
}
Ok(()) Ok(())
} }

View file

@ -1,20 +1,24 @@
use std::fmt::Display; use std::fmt::Display;
use std::path::Path; use std::path::Path;
use std::process::exit;
use log::{debug, info, trace}; use log::{debug, error, info, trace};
use reqwest::blocking::get; use reqwest::blocking::get;
use manifest::build::Build;
use pkgfile::PKGFile; use pkgfile::PKGFile;
use crate::package::identifier::PackageIdentifier; use crate::package::identifier::{PackageIdentifier, PackageLocator};
use crate::types::fetch::TryFetch; use crate::types::fetch::TryFetch;
pub mod identifier; pub mod identifier;
pub mod installer; pub mod installer;
pub mod queue;
#[derive(Eq, PartialEq)]
pub struct Package { pub struct Package {
pub identifier: identifier::PackageIdentifier, pub identifier: PackageIdentifier,
pub pkgfile: pkgfile::PKGFile, pub pkgfile: PKGFile,
is_installed: bool, is_installed: bool,
is_indexed: bool, is_indexed: bool,
} }
@ -35,6 +39,55 @@ impl Package {
manifest::Manifest::try_from(self.pkgfile.manifest.clone()).unwrap() manifest::Manifest::try_from(self.pkgfile.manifest.clone()).unwrap()
} }
/// Get package dependencies
pub fn dependencies(&self) -> Vec<Package> {
let mut dependencies = vec![];
for dependency in self.manifest().dependencies {
let pkglocate = if let Ok(pl) = PackageLocator::try_from(dependency.clone()) {
trace!("parsed pl successfully...");
pl
} else {
error!("Could not parse package locator: {:?} in dependencies.", &dependency);
exit(1);
};
let pkg = match Package::try_fetch(PackageIdentifier::PackageLocator(pkglocate)) {
Ok(p) => p,
Err(e) => {
error!("Could not fetch dependency: {}", e);
exit(1);
}
};
dependencies.push(pkg);
}
dependencies
}
pub fn build_dependencies(&self) -> Vec<Package> {
let mut dependencies = vec![];
for dependency in self
.manifest()
.build
.unwrap_or(Build::default())
.dependencies {
let pkglocate = if let Ok(pl) = PackageLocator::try_from(dependency.clone()) {
trace!("parsed pl successfully...");
pl
} else {
error!("Could not parse package locator: {:?} in dependencies.", &dependency);
exit(1);
};
let pkg = match Package::try_fetch(PackageIdentifier::PackageLocator(pkglocate)) {
Ok(p) => p,
Err(e) => {
error!("Could not fetch dependency: {}", e);
exit(1);
}
};
dependencies.push(pkg);
}
dependencies
}
/// Install the package. /// Install the package.
pub fn install(&mut self, build: bool) -> Result<(), installer::errors::InstallError> { pub fn install(&mut self, build: bool) -> Result<(), installer::errors::InstallError> {
let manifest = self.manifest(); let manifest = self.manifest();
@ -119,7 +172,7 @@ impl TryFetch<PackageIdentifier> for Package {
if let Ok(b) = response.bytes() { if let Ok(b) = response.bytes() {
bytes.extend(b); bytes.extend(b);
} }
}, }
Err(e) => return Err(FetchError::HTTPError(e)), Err(e) => return Err(FetchError::HTTPError(e)),
}; };
// parse bytes as PKGFile // parse bytes as PKGFile

37
pkgr/src/package/queue.rs Normal file
View file

@ -0,0 +1,37 @@
use log::trace;
use crate::package::Package;
pub struct PackageQueue {
packages: Vec<Package>
}
impl PackageQueue {
pub fn new() -> Self {
PackageQueue {
packages: vec![]
}
}
pub fn add_package(&mut self, package: Package, build: bool) {
let dependencies = package.dependencies();
for dependency in dependencies {
trace!("Checking package: {}", &dependency.identifier);
if self.packages.contains(&dependency) {
continue
}
trace!("Adding package: {}", &dependency.identifier);
self.packages.push(dependency);
}
if !self.packages.contains(&package) {
self.packages.push(package);
}
}
pub fn install(&mut self, build: bool) {
self.packages
.iter_mut()
.for_each(|pkg| {
pkg.install(build);
});
}
}