diff --git a/manifest/src/build.rs b/manifest/src/build.rs index 161b785..1879710 100644 --- a/manifest/src/build.rs +++ b/manifest/src/build.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Build { - build_script: String, - install_script: String, - dependencies: HashMap, + pub build_script: String, + pub install_script: String, + pub dependencies: HashMap, } diff --git a/pkgfile/src/lib.rs b/pkgfile/src/lib.rs index f7768b0..407055c 100644 --- a/pkgfile/src/lib.rs +++ b/pkgfile/src/lib.rs @@ -1,4 +1,4 @@ -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PKGFile { pub manifest: String, pub data: Vec, diff --git a/pkgr/src/commands.rs b/pkgr/src/commands.rs index cc3dfcf..2265330 100644 --- a/pkgr/src/commands.rs +++ b/pkgr/src/commands.rs @@ -4,7 +4,7 @@ use clap::{Parser, Subcommand}; use log::{debug, error, info, trace, warn}; use manifest::Manifest; use crate::package::installer::{InstallType, PackageInstaller}; -use crate::package::fetch::fetch_package; +use crate::package::Package; #[derive(Parser, Debug)] #[clap(name = "pkgr", version)] @@ -58,31 +58,35 @@ impl Command { info!("Parsing package..."); trace!("Fetching package: {}", package_identifier); - let pkgfile = fetch_package(package_identifier.clone()).unwrap(); - debug!("size: manifest({}kb) data({}kb)", pkgfile.manifest.len() / 1024, pkgfile.data.len() / 1024); - trace!("parsing manifest"); - let manifest = Manifest::try_from(pkgfile.manifest.clone()).unwrap(); - debug!("manifest pkg name: {}", manifest.package.name); - trace!("creating installer"); - let installer = PackageInstaller::new(manifest.clone(), pkgfile, if *build { InstallType::Build } else { InstallType::Bin }); - info!("Installing: {}...", &manifest.package.name); + let mut pkg = Package::fetch(package_identifier.clone()).unwrap(); + debug!("manifest size: {}kb", pkg.pkgfile.manifest.len() / 1024); + debug!("files size: {}kb", pkg.pkgfile.data.len() / 1024); - trace!("starting install"); - match installer.install() { - Ok(_) => { - info!("Sucessfully installed: {}", &manifest.package.name); - () - }, + trace!("Checking if package is installed..."); + if pkg.is_installed() { + error!("Package is already installed."); + exit(1); + } + + trace!("Starting install..."); + match pkg.install() { + Ok(_) => (), Err(e) => { - error!("{}", e.to_string()); + error!("Install failed: {}", e.to_string()); exit(1); } } - let unix_end = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap(); + let end = std::time::Instant::now(); - // float ms - let duration = (end - start).as_nanos() as f64; - info!("Install took: {}ms", (duration / 1_000_000.0)); + let unix_end = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap(); + + let duration = end.duration_since(start); + + info!("Install complete."); + info!("Install took {}ms.", duration.as_nanos() as f64 / 1000000.0); + } Command::Remove { package_identifier, index } => { if let PackageIdentifier::URI(_) = package_identifier { diff --git a/pkgr/src/package/fetch.rs b/pkgr/src/package/fetch.rs index 0e68045..099c5b2 100644 --- a/pkgr/src/package/fetch.rs +++ b/pkgr/src/package/fetch.rs @@ -1,11 +1,9 @@ use std::error::Error; use std::fmt::Display; -use std::fs::File; use std::io::Read; -use log::warn; use pkgfile::PKGFile; -use crate::package::identifier::PackageIdentifier; use reqwest::blocking::get; +use crate::package::identifier::PackageLocator; #[derive(Debug)] pub enum FetchError { @@ -26,34 +24,33 @@ impl Display for FetchError { impl Error for FetchError {} -pub fn fetch_package(package_identifier: PackageIdentifier) -> Result { - match package_identifier { - PackageIdentifier::Path(path) => { - std::fs::read(path) - .map_err(|e| FetchError::IOError(e)).and_then(|bytes| { - PKGFile::try_from(bytes).map_err(|_| FetchError::ParseError) - }) - } - PackageIdentifier::URI(uri) => { - // get file contents as bytes - let mut bytes = Vec::new(); - match get(&uri) { - Ok(mut 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)), +pub fn fetch_by_path>(path: S) -> Result { + 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>(uri: S) -> Result { + // get file contents as bytes + let mut bytes = Vec::new(); + match get(uri.into()) { + Ok(mut response) => { + match response.take(1024 * 1024).read_to_end(&mut bytes) { + Ok(_) => (), + Err(e) => return Err(FetchError::IOError(e)), }; - // parse bytes as PKGFile - match PKGFile::try_from(bytes) { - Ok(pkgfile) => Ok(pkgfile), - Err(e) => Err(FetchError::ParseError), - } - } - PackageIdentifier::PackageLocator(package_locator) => { - Ok(PKGFile::default()) } + 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), } -} \ No newline at end of file +} + +pub fn fetch_by_package_locator(package_locator: PackageLocator) -> Result { + // TODO: search index for package locator + Ok(PKGFile::default()) +} diff --git a/pkgr/src/package/installer/errors.rs b/pkgr/src/package/installer/errors.rs index e5f62d6..a6801c0 100644 --- a/pkgr/src/package/installer/errors.rs +++ b/pkgr/src/package/installer/errors.rs @@ -14,7 +14,9 @@ impl Display for BinError { } #[derive(Debug)] -pub enum BuildError {} +pub enum BuildError { + InvalidManifest +} impl Display for BuildError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -28,7 +30,7 @@ impl Display for BuildError { pub enum InstallError { BuildError(BuildError), BinError(BinError), - InstallError + Generic } impl ToString for InstallError { @@ -36,7 +38,7 @@ impl ToString for InstallError { match self { InstallError::BuildError(e) => format!("Build error: {}", e), InstallError::BinError(e) => format!("Bin error: {}", e), - InstallError::InstallError => "Install error".to_string(), + InstallError::Generic => "Install error".to_string(), } } } diff --git a/pkgr/src/package/installer/mod.rs b/pkgr/src/package/installer/mod.rs index 53602c6..8f75941 100644 --- a/pkgr/src/package/installer/mod.rs +++ b/pkgr/src/package/installer/mod.rs @@ -54,6 +54,13 @@ impl PackageInstaller { } fn build(&self) -> Result<(), BuildError> { + if let None = self.manifest.build.clone() { + return Err(BuildError::InvalidManifest); + } + let build_manifest = self.manifest.build.clone().unwrap(); + // TODO: Check dependencies + + Ok(()) } diff --git a/pkgr/src/package/mod.rs b/pkgr/src/package/mod.rs index f838f7e..349c360 100644 --- a/pkgr/src/package/mod.rs +++ b/pkgr/src/package/mod.rs @@ -1,3 +1,68 @@ +use log::trace; + pub mod identifier; pub mod installer; -pub mod fetch; \ No newline at end of file +pub mod fetch; + +pub struct Package { + pub identifier: identifier::PackageIdentifier, + pub pkgfile: pkgfile::PKGFile, + is_installed: bool, + is_indexed: bool, +} + +impl Package { + pub fn new(identifier: identifier::PackageIdentifier, pkgfile: pkgfile::PKGFile) -> Package { + Package { + identifier, + pkgfile, + is_installed: false, + is_indexed: false, + } + } + + pub fn manifest(&self) -> manifest::Manifest { + manifest::Manifest::try_from(self.pkgfile.manifest.clone()) + .unwrap() + } + + pub fn fetch(package_identifier: identifier::PackageIdentifier) -> Result { + 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)) + }, + } + } + + pub fn install(&mut self) -> Result<(), installer::errors::InstallError> { + let manifest = self.manifest(); + let installer = installer::PackageInstaller::new(manifest.clone(), self.pkgfile.clone(), installer::InstallType::Bin); + match installer.install() { + Ok(_) => { + self.is_installed = true; + Ok(()) + }, + Err(e) => Err(e) + } + } + + pub fn is_installed(&self) -> bool { + self.is_installed + } + + pub fn is_indexed(&self) -> bool { + self.is_indexed + } +} \ No newline at end of file