190 lines
No EOL
5.9 KiB
Rust
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))
|
|
}
|
|
} |