use crate::tmpfs::TempDir; use errors::{BinError, BuildError, InstallError}; use log::{debug, error, info, trace}; use manifest::Manifest; use pkgfile::PKGFile; use std::fmt::Display; use std::process::exit; use crate::CONFIG; use crate::package::identifier::{PackageIdentifier, PackageLocator}; use crate::package::Package; pub mod errors; #[derive(Debug)] pub enum InstallType { Build, Bin, } #[derive(Debug)] pub struct PackageInstaller { manifest: Manifest, pkgfile: PKGFile, install_type: InstallType, } impl PackageInstaller { pub fn new(m: Manifest, p: PKGFile, i: InstallType) -> PackageInstaller { PackageInstaller { manifest: m, pkgfile: p, install_type: i, } } fn extract_to(&self, path: String) -> Result<(), BinError> { if !self.pkgfile.has_data() { return Err(BinError::UnpackError("package has no data".to_string())); } if std::path::Path::new(&path).exists() { return Err(BinError::UnpackError("path already exists".to_string())); } tar::Archive::new(self.pkgfile.data.as_slice()) .unpack(&path) .map_err(|e| BinError::UnpackError(e.to_string())) } fn bin(&self) -> Result<(), BinError> { let mut tmpdir = TempDir::default(); tmpdir.push(&self.manifest.package.name); trace!("extracting package into: {}", tmpdir.to_string()); match self.extract_to(tmpdir.to_string()) { Ok(_) => {} Err(e) => return Err(e), } debug!("extracted package in: {}", tmpdir.to_string()); Ok(()) } 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 for pkg_tuple in build_manifest.dependencies { let mut pkg = Package::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(()) } pub fn install(&mut self) -> Result<(), InstallError> { match self.install_type { InstallType::Bin => { if let None = self.manifest.bin { self.install_type = InstallType::Build; if let None = self.manifest.build { return Err(InstallError::InvalidManifest); } } } InstallType::Build => { if let None = self.manifest.build { self.install_type = InstallType::Bin; if let None = self.manifest.bin { return Err(InstallError::InvalidManifest); } } } } match self.install_type { InstallType::Bin => self.bin() .map_err(|e| InstallError::BinError(e)), InstallType::Build => self.build() .map_err(|e| InstallError::BuildError(e)), } } }