diff --git a/src/creator/mod.rs b/src/creator/mod.rs index 866cd10..c6423bd 100644 --- a/src/creator/mod.rs +++ b/src/creator/mod.rs @@ -1,11 +1,14 @@ +use hpk_package::deku::DekuError; + use { - crate::{Item, Package, Plist, Specs}, - hpk_package::Entry, + crate::{Item, ItemError, Package, Plist, Specs}, + hpk_package::{tar, Entry}, rayon::prelude::{IntoParallelRefIterator, ParallelIterator}, std::{ borrow::BorrowMut, env, error::Error, + fmt, fs::{self, File}, io::{self, Write}, path::{Path, PathBuf}, @@ -19,10 +22,10 @@ use { zstd::Encoder, }; +#[derive(Debug, Clone)] pub enum Message { MemberAdded(String), Success(String), - Failure(String), } /// Creates a package archive @@ -90,51 +93,38 @@ impl Creator { archive.set_extension("tar.zst"); let fd = File::create(&archive)?; let writer = Mutex::new(Encoder::new(fd, 0)?); - let sender = Mutex::new(sender); env::set_current_dir(&self.path)?; + let s = sender.clone(); self.entries .par_iter() .filter(|x| x.as_path() != Path::new(".")) - .for_each(|x| { - let sender = sender.lock().unwrap().clone(); - if let Ok(item) = Item::try_create(x.as_path()) { - if let Entry::File { - path: _, + .try_for_each_with(s, |s, x| { + let item = Item::try_create(x.as_path())?; + if let Entry::File { + path: _, + sha256sum: _, + mode: _, + size, + } = &item.entry + { + totalsize.fetch_add(*size, Ordering::Release); + } + let path = match item.entry.clone() { + Entry::File { + path, sha256sum: _, mode: _, - size, - } = &item.entry - { - totalsize.fetch_add(*size, Ordering::Release); + size: _, } - let path = match item.entry.clone() { - Entry::File { - path, - sha256sum: _, - mode: _, - size: _, - } - | Entry::Link { path, target: _ } - | Entry::Directory { path, mode: _ } => path, - }; - plist.lock().unwrap().borrow_mut().entries.push(item.entry); - match writer.lock().unwrap().borrow_mut().write_all(&item.data) { - Ok(_) => sender - .send(Message::MemberAdded(format!("{}", path.display()))) - .expect("couldn't send message"), - Err(e) => sender - .send(Message::Failure(format!("{e}"))) - .expect("couldn't send message"), - } - } else { - sender - .send(Message::Failure(format!( - "Could not process DirEntry for {}", - x.display() - ))) - .expect("could not send message"); - } - }); + | Entry::Link { path, target: _ } + | Entry::Directory { path, mode: _ } => path, + }; + plist.lock().unwrap().borrow_mut().entries.push(item.entry); + writer.lock().unwrap().borrow_mut().write_all(&item.data)?; + s.send(Message::MemberAdded(format!("{}", path.display()))) + .expect("couldn't send message"); + Ok::<(), CreationError>(()) + })?; let mut package: Package = self.specs.into(); package.size = totalsize.into_inner(); let plist = plist.into_inner()?; @@ -143,9 +133,50 @@ impl Creator { let mut writer = writer.into_inner()?; writer.write_all(&node.to_vec()?)?; let _fd = writer.finish()?; - let sender = sender.into_inner()?; sender.send(Message::Success(format!("{} saved", archive.display())))?; env::set_current_dir(d)?; Ok(()) } } + +#[derive(Debug)] +pub enum CreationError { + Io(io::Error), + Fmt(fmt::Error), + Tar(tar::Error), + Deku(DekuError), +} + +impl fmt::Display for CreationError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{self:?}") + } +} + +impl Error for CreationError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + Self::Io(e) => Some(e), + Self::Fmt(e) => Some(e), + Self::Tar(e) => Some(e), + Self::Deku(e) => Some(e), + } + } +} + +impl From for CreationError { + fn from(value: io::Error) -> Self { + Self::Io(value) + } +} + +impl From for CreationError { + fn from(value: ItemError) -> Self { + match value { + ItemError::Io(e) => Self::Io(e), + ItemError::Fmt(e) => Self::Fmt(e), + ItemError::Tar(e) => Self::Tar(e), + ItemError::Deku(e) => Self::Deku(e), + } + } +} diff --git a/src/hpk.rs b/src/hpk.rs index 7073466..a324e53 100644 --- a/src/hpk.rs +++ b/src/hpk.rs @@ -3,7 +3,7 @@ mod cli; use { clap::ArgMatches, cli::cli, - hpk::{Creator, Dependency, Message, Specs, Version}, + hpk::{CreationError, Creator, Dependency, Message, Specs, Version}, indicatif::{ProgressBar, ProgressStyle}, ron::ser::{to_writer_pretty, PrettyConfig}, std::{ @@ -93,13 +93,9 @@ fn create(matches: &ArgMatches) -> Result<(), Box> { pb.inc(1); pb.finish_and_clear(); } - Message::Failure(s) => { - eprint!("{s}"); - return Err(io::Error::new(io::ErrorKind::Other, s)); - } } } - Ok(()) + Ok::<(), CreationError>(()) }); creator.create(&outdir, sender)?; match handle.join() { diff --git a/src/installer/mod.rs b/src/installer/mod.rs index 396ac99..1c26d18 100644 --- a/src/installer/mod.rs +++ b/src/installer/mod.rs @@ -175,7 +175,11 @@ impl Installer { } } -fn extract_entry(entry: &Entry, node: &Node, path: PathBuf) -> Result { +fn extract_entry( + entry: &Entry, + node: &Node, + path: PathBuf, +) -> Result { match entry { Entry::Directory { path: _, mode } => { DirBuilder::new().mode(*mode).create(&path)?; diff --git a/src/item/mod.rs b/src/item/mod.rs index f287b93..06c4fd2 100644 --- a/src/item/mod.rs +++ b/src/item/mod.rs @@ -1,14 +1,15 @@ use hpk_package::{ + deku::DekuError, sha2::{Digest, Sha256}, - tar::{Node, Owner}, + tar::{Error as TarError, Node, Owner}, Entry, }; use std::{ error::Error, ffi::OsStr, - fmt::Write, + fmt::{self, Write}, fs, - io::Read, + io::{self, Read}, os::unix::fs::MetadataExt, path::{Path, PathBuf}, }; @@ -21,7 +22,7 @@ pub struct Item { } impl Item { - pub fn try_create(path: &Path) -> Result> { + pub fn try_create(path: &Path) -> Result { let path = fix_path(path); let meta = fs::metadata(&path)?; let filename = format!("{}", path.display()); @@ -68,6 +69,55 @@ impl Item { } } +#[derive(Debug)] +pub enum ItemError { + Io(io::Error), + Fmt(fmt::Error), + Tar(TarError), + Deku(DekuError), +} + +impl fmt::Display for ItemError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{self:?}") + } +} + +impl Error for ItemError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + Self::Io(e) => Some(e), + Self::Fmt(e) => Some(e), + Self::Tar(e) => Some(e), + Self::Deku(e) => Some(e), + } + } +} + +impl From for ItemError { + fn from(value: io::Error) -> Self { + Self::Io(value) + } +} + +impl From for ItemError { + fn from(value: fmt::Error) -> Self { + Self::Fmt(value) + } +} + +impl From for ItemError { + fn from(value: TarError) -> Self { + Self::Tar(value) + } +} + +impl From for ItemError { + fn from(value: DekuError) -> Self { + Self::Deku(value) + } +} + fn fix_path(path: &Path) -> PathBuf { let path = if let Ok(p) = path.strip_prefix("./") { p diff --git a/src/lib.rs b/src/lib.rs index ce09a1c..ba57571 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,12 +9,12 @@ mod repository; use std::path::PathBuf; pub use { - creator::{Creator, Message}, + creator::{CreationError, Creator, Message}, db::Database, hooks::{Hooks, Pinstall}, hpk_package::{tar, Arch, Dependency, GitRev, Package, Plist, Rapid, SemVer, Specs, Version}, installer::{InstallError, InstallMessage, Installer}, - item::Item, + item::{Item, ItemError}, repository::Repository, };