packager/pkgr/src/package/mod.rs

190 lines
No EOL
5.9 KiB
Rust

use std::fmt::Display;
use std::path::Path;
use std::process::exit;
use log::{debug, error, info, trace};
use reqwest::blocking::get;
use manifest::build::Build;
use pkgfile::PKGFile;
use crate::package::identifier::{PackageIdentifier, PackageLocator};
use crate::types::fetch::TryFetch;
pub mod identifier;
pub mod installer;
pub mod queue;
#[derive(Eq, PartialEq)]
pub struct Package {
pub identifier: PackageIdentifier,
pub pkgfile: PKGFile,
is_installed: bool,
is_indexed: bool,
}
impl Package {
/// Create a new package from a package identifier and a package file.
pub fn new(identifier: PackageIdentifier, pkgfile: PKGFile) -> Package {
Package {
identifier,
pkgfile,
is_installed: false,
is_indexed: false,
}
}
/// Get the package manifest.
pub fn manifest(&self) -> manifest::Manifest {
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.
pub fn install(&mut self, build: bool) -> Result<(), installer::errors::InstallError> {
let manifest = self.manifest();
let mut installer = installer::PackageInstaller::new(
manifest.clone(),
self.pkgfile.clone(),
if build {
info!("building package: {}...", if self.manifest().package.name.is_empty() {
self.identifier.to_string()
} else {
self.manifest().package.name
});
installer::InstallType::Build
} else {
info!("using binary install for package: {}...", if self.manifest().package.name.is_empty() {
self.identifier.to_string()
} else {
self.manifest().package.name
});
installer::InstallType::Bin
},
);
match installer.install() {
Ok(_) => {
self.is_installed = true;
Ok(())
}
Err(e) => Err(e),
}
}
/// Check if the package is installed.
pub fn is_installed(&self) -> bool {
self.is_installed
}
/// Check if the package is indexed.
pub fn is_indexed(&self) -> bool {
self.is_indexed
}
/// Remove the package from the system.
pub fn remove(&mut self) -> Result<(), ()> {
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> {
trace!("Fetching: {query:#?}");
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();
debug!("sending GET request...");
match get::<String>(s.into()) {
Ok(response) => {
debug!("Got 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) => unimplemented!()
};
pkgfile
.map(|p| Package::new(query, p))
}
}