refactor: changed structure.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
6335be4b04
commit
759c219f96
8 changed files with 113 additions and 89 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PKGFile {
|
pub struct PKGFile {
|
||||||
pub manifest: String,
|
pub manifest: String,
|
||||||
|
@ -23,28 +28,56 @@ impl Default for PKGFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Vec<u8>> for PKGFile {
|
#[derive(Debug)]
|
||||||
type Error = ();
|
pub enum PKGFileError {
|
||||||
|
IOError(io::Error),
|
||||||
|
ParsingError(String)
|
||||||
|
}
|
||||||
|
|
||||||
fn try_from(value: Vec<u8>) -> Result<Self, ()> {
|
impl Display for PKGFileError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
PKGFileError::IOError(e) => write!(f, "IOError: {}", e),
|
||||||
|
PKGFileError::ParsingError(s) => write!(f, "ParsingError: {}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for PKGFileError {}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<&'a Path> for PKGFile {
|
||||||
|
type Error = PKGFileError;
|
||||||
|
fn try_from(path: &'a Path) -> Result<Self, Self::Error> {
|
||||||
|
let d = match std::fs::read(path) {
|
||||||
|
Ok(d) => d,
|
||||||
|
Err(e) => return Err(PKGFileError::IOError(e))
|
||||||
|
};
|
||||||
|
PKGFile::try_from(d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Vec<u8>> for PKGFile {
|
||||||
|
type Error = PKGFileError;
|
||||||
|
|
||||||
|
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||||
match value[0] {
|
match value[0] {
|
||||||
1 => {
|
1 => {
|
||||||
let header: Vec<u32> = value[..3].iter().map(|v| u32::from(*v)).collect();
|
let header: Vec<u32> = value[..3].iter().map(|v| u32::from(*v)).collect();
|
||||||
let manifest_size: u32 = (header[1] << 8) | header[2];
|
let manifest_size: u32 = (header[1] << 8) | header[2];
|
||||||
if manifest_size > value.len() as u32 {
|
if manifest_size > value.len() as u32 {
|
||||||
return Err(());
|
return Err(PKGFileError::ParsingError("Invalid header length".into()));
|
||||||
}
|
}
|
||||||
Ok(PKGFile {
|
Ok(PKGFile {
|
||||||
manifest: match String::from_utf8(
|
manifest: match String::from_utf8(
|
||||||
value[3..(manifest_size as usize + 3)].to_vec(),
|
value[3..(manifest_size as usize + 3)].to_vec(),
|
||||||
) {
|
) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
_ => return Err(()),
|
_ => return Err(PKGFileError::ParsingError("Could not parse manifest".into())),
|
||||||
},
|
},
|
||||||
data: value[(manifest_size as usize + 3)..].to_vec(),
|
data: value[(manifest_size as usize + 3)..].to_vec(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
_ => Err(PKGFileError::ParsingError("Unknown pkgfile version".into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ use log::{debug, error, info, trace, warn};
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use crate::CONFIG;
|
use crate::CONFIG;
|
||||||
use crate::process::Process;
|
use crate::process::Process;
|
||||||
|
use crate::types::fetch::TryFetch;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[clap(name = "pkgr", version)]
|
#[clap(name = "pkgr", version)]
|
||||||
|
@ -60,7 +61,7 @@ impl Command {
|
||||||
|
|
||||||
info!("Parsing package...");
|
info!("Parsing package...");
|
||||||
trace!("Fetching package: {}", package_identifier);
|
trace!("Fetching package: {}", package_identifier);
|
||||||
let mut pkg = Package::fetch(package_identifier.clone()).unwrap();
|
let mut pkg = Package::try_fetch(package_identifier.clone()).unwrap();
|
||||||
debug!("manifest size: {}kb", pkg.pkgfile.manifest.len() / 1024);
|
debug!("manifest size: {}kb", pkg.pkgfile.manifest.len() / 1024);
|
||||||
debug!("files size: {}kb", pkg.pkgfile.data.len() / 1024);
|
debug!("files size: {}kb", pkg.pkgfile.data.len() / 1024);
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@ use clap::Parser;
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
|
|
||||||
mod commands;
|
mod commands;
|
||||||
mod logging;
|
mod logging;
|
||||||
mod package;
|
mod package;
|
||||||
mod process;
|
mod process;
|
||||||
mod tmpfs;
|
mod tmpfs;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod types;
|
||||||
|
|
||||||
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")
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
use crate::package::identifier::PackageLocator;
|
|
||||||
use pkgfile::PKGFile;
|
|
||||||
use reqwest::blocking::get;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::io::Read;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum FetchError {
|
|
||||||
HTTPError(reqwest::Error),
|
|
||||||
IOError(std::io::Error),
|
|
||||||
ParseError,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for FetchError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
FetchError::HTTPError(e) => write!(f, "HTTP Error: {}", e),
|
|
||||||
FetchError::IOError(e) => write!(f, "IO Error: {}", e),
|
|
||||||
FetchError::ParseError => write!(f, "Parse Error"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for FetchError {}
|
|
||||||
|
|
||||||
pub fn fetch_by_path<S: Into<String>>(path: S) -> Result<PKGFile, FetchError> {
|
|
||||||
std::fs::read(path.into())
|
|
||||||
.map_err(|e| FetchError::IOError(e))
|
|
||||||
.and_then(|bytes| PKGFile::try_from(bytes).map_err(|_| FetchError::ParseError))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fetch_by_uri<S: Into<String>>(uri: S) -> Result<PKGFile, FetchError> {
|
|
||||||
// get file contents as bytes
|
|
||||||
let mut bytes = Vec::new();
|
|
||||||
match get(uri.into()) {
|
|
||||||
Ok(response) => {
|
|
||||||
match response.take(1024 * 1024).read_to_end(&mut bytes) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(e) => return Err(FetchError::IOError(e)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Err(e) => return Err(FetchError::HTTPError(e)),
|
|
||||||
};
|
|
||||||
// parse bytes as PKGFile
|
|
||||||
match PKGFile::try_from(bytes) {
|
|
||||||
Ok(pkgfile) => Ok(pkgfile),
|
|
||||||
Err(_e) => Err(FetchError::ParseError),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fetch_by_package_locator(_package_locator: PackageLocator) -> Result<PKGFile, FetchError> {
|
|
||||||
// TODO: search index for package locator
|
|
||||||
Ok(PKGFile::default())
|
|
||||||
}
|
|
|
@ -8,6 +8,7 @@ use std::process::exit;
|
||||||
use crate::CONFIG;
|
use crate::CONFIG;
|
||||||
use crate::package::identifier::{PackageIdentifier, PackageLocator};
|
use crate::package::identifier::{PackageIdentifier, PackageLocator};
|
||||||
use crate::package::Package;
|
use crate::package::Package;
|
||||||
|
use crate::types::fetch::TryFetch;
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ 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 {
|
for pkg_tuple in build_manifest.dependencies {
|
||||||
let mut pkg = Package::fetch(
|
let mut pkg = Package::try_fetch(
|
||||||
PackageIdentifier::PackageLocator(
|
PackageIdentifier::PackageLocator(
|
||||||
PackageLocator::from(pkg_tuple)
|
PackageLocator::from(pkg_tuple)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::path::Path;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
|
use reqwest::blocking::get;
|
||||||
|
use pkgfile::PKGFile;
|
||||||
|
use crate::package::identifier::PackageIdentifier;
|
||||||
|
use crate::types::fetch::TryFetch;
|
||||||
|
|
||||||
pub mod fetch;
|
|
||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
pub mod installer;
|
pub mod installer;
|
||||||
|
|
||||||
|
@ -13,7 +18,7 @@ pub struct Package {
|
||||||
|
|
||||||
impl Package {
|
impl Package {
|
||||||
/// Create a new package from a package identifier and a package file.
|
/// Create a new package from a package identifier and a package file.
|
||||||
pub fn new(identifier: identifier::PackageIdentifier, pkgfile: pkgfile::PKGFile) -> Package {
|
pub fn new(identifier: PackageIdentifier, pkgfile: PKGFile) -> Package {
|
||||||
Package {
|
Package {
|
||||||
identifier,
|
identifier,
|
||||||
pkgfile,
|
pkgfile,
|
||||||
|
@ -22,29 +27,6 @@ impl Package {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch a package from a package identifier.
|
|
||||||
pub fn fetch(
|
|
||||||
package_identifier: identifier::PackageIdentifier,
|
|
||||||
) -> Result<Package, fetch::FetchError> {
|
|
||||||
match &package_identifier {
|
|
||||||
identifier::PackageIdentifier::Path(path) => {
|
|
||||||
trace!("fetching package from path: {}", path);
|
|
||||||
let pkgfile = fetch::fetch_by_path(path).unwrap();
|
|
||||||
Ok(Package::new(package_identifier, pkgfile))
|
|
||||||
}
|
|
||||||
identifier::PackageIdentifier::URI(url) => {
|
|
||||||
trace!("fetching package from uri: {}", url);
|
|
||||||
let pkgfile = fetch::fetch_by_uri(url).unwrap();
|
|
||||||
Ok(Package::new(package_identifier, pkgfile))
|
|
||||||
}
|
|
||||||
identifier::PackageIdentifier::PackageLocator(locator) => {
|
|
||||||
trace!("fetching package from locator: {}", locator);
|
|
||||||
let pkgfile = fetch::fetch_by_package_locator(locator.clone()).unwrap();
|
|
||||||
Ok(Package::new(package_identifier, pkgfile))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the package manifest.
|
/// Get the package manifest.
|
||||||
pub fn manifest(&self) -> manifest::Manifest {
|
pub fn manifest(&self) -> manifest::Manifest {
|
||||||
manifest::Manifest::try_from(self.pkgfile.manifest.clone()).unwrap()
|
manifest::Manifest::try_from(self.pkgfile.manifest.clone()).unwrap()
|
||||||
|
@ -96,3 +78,54 @@ impl Package {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum FetchError {
|
||||||
|
HTTPError(reqwest::Error),
|
||||||
|
IOError(std::io::Error),
|
||||||
|
ParseError,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for FetchError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
FetchError::HTTPError(e) => write!(f, "HTTP Error: {}", e),
|
||||||
|
FetchError::IOError(e) => write!(f, "IO Error: {}", e),
|
||||||
|
FetchError::ParseError => write!(f, "Parse Error"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFetch<PackageIdentifier> for Package {
|
||||||
|
type Error = FetchError;
|
||||||
|
|
||||||
|
/// Fetch a package from a package identifier.
|
||||||
|
fn try_fetch(query: PackageIdentifier) -> Result<Package, Self::Error> {
|
||||||
|
let pkgfile = match &query {
|
||||||
|
PackageIdentifier::Path(s) => match PKGFile::try_from(Path::new(&s)) {
|
||||||
|
Ok(p) => Ok(p),
|
||||||
|
Err(e) => Err(FetchError::ParseError)
|
||||||
|
},
|
||||||
|
PackageIdentifier::URI(s) => {
|
||||||
|
let mut bytes = Vec::new();
|
||||||
|
match get::<String>(s.into()) {
|
||||||
|
Ok(response) => {
|
||||||
|
if let Ok(b) = response.bytes() {
|
||||||
|
bytes.extend(b);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => return Err(FetchError::HTTPError(e)),
|
||||||
|
};
|
||||||
|
// parse bytes as PKGFile
|
||||||
|
match PKGFile::try_from(bytes) {
|
||||||
|
Ok(pkgfile) => Ok(pkgfile),
|
||||||
|
Err(_e) => Err(FetchError::ParseError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PackageIdentifier::PackageLocator(l) => Ok(PKGFile::default())
|
||||||
|
};
|
||||||
|
|
||||||
|
pkgfile
|
||||||
|
.map(|p| Package::new(query, p))
|
||||||
|
}
|
||||||
|
}
|
10
pkgr/src/types/fetch.rs
Normal file
10
pkgr/src/types/fetch.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/// Get a result from an external source
|
||||||
|
pub trait Fetch<Q, R = Self> {
|
||||||
|
fn fetch(query: Q) -> R;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Try to get a result from an external source
|
||||||
|
pub trait TryFetch<Q, R = Self> {
|
||||||
|
type Error;
|
||||||
|
fn try_fetch(query: Q) -> Result<R, Self::Error>;
|
||||||
|
}
|
1
pkgr/src/types/mod.rs
Normal file
1
pkgr/src/types/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod fetch;
|
Loading…
Reference in a new issue