diff --git a/.gitignore b/.gitignore index 83a0302..985a402 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ /target /Cargo.lock -test +tags diff --git a/src/creator/mod.rs b/src/creator/mod.rs deleted file mode 100644 index e143601..0000000 --- a/src/creator/mod.rs +++ /dev/null @@ -1,143 +0,0 @@ -use { - crate::{Entry, Item, Package, Plist, Specs}, - rayon::prelude::{IntoParallelRefIterator, ParallelIterator}, - std::{ - borrow::BorrowMut, - env, - error::Error, - fs::{self, File}, - io::{self, Write}, - path::{Path, PathBuf}, - sync::{ - atomic::{AtomicUsize, Ordering}, - mpsc::Sender, - Mutex, - }, - }, - walkdir::WalkDir, - zstd::Encoder, -}; - -pub enum Message { - MemberAdded(String), - Success(String), - Failure(String), -} - -pub struct Creator { - path: PathBuf, - entries: Vec, - specs: Specs, -} - -impl Creator { - pub fn new(path: &Path, specs: Specs) -> Result { - let d = env::current_dir()?; - env::set_current_dir(path)?; - let path = path.to_path_buf(); - let entries = WalkDir::new(".") - .into_iter() - .filter(Result::is_ok) - .map(|x| x.unwrap().path().to_path_buf()) - .collect::>(); - env::set_current_dir(d)?; - Ok(Self { - path, - entries, - specs, - }) - } - - pub fn from_list(list: &[&str], specs: Specs) -> Result { - let entries = list.iter().map(|x| Path::new(x).to_path_buf()).collect(); - Ok(Self { - path: env::current_dir().unwrap_or(Path::new("/").to_path_buf()), - entries, - specs, - }) - } - - pub fn len(&self) -> usize { - self.entries.len() - } - - pub fn is_empty(&self) -> bool { - self.entries.is_empty() - } - - pub fn create(self, outdir: &Path, sender: Sender) -> Result<(), Box> { - let d = env::current_dir()?; - let plist = Mutex::new(Plist::default()); - let totalsize: AtomicUsize = 0.into(); - let fullname = format!( - "{}-{}_{}", - &self.specs.name, self.specs.version, self.specs.release - ); - if !outdir.exists() { - fs::create_dir_all(outdir)?; - } - let outdir = outdir.canonicalize()?; - let mut archive = outdir.clone(); - archive.push(&fullname); - 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)?; - 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: _, - sha256sum: _, - mode: _, - size, - } = &item.entry - { - totalsize.fetch_add(*size, Ordering::Release); - } - 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"); - } - }); - let mut package: Package = self.specs.into(); - package.size = totalsize.into_inner(); - let plist = plist.into_inner()?; - package.plist = plist; - let node = package.save_ron_and_create_tar_node(&outdir)?; - 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(()) - } -} diff --git a/src/item/mod.rs b/src/item/mod.rs deleted file mode 100644 index 6e2c60c..0000000 --- a/src/item/mod.rs +++ /dev/null @@ -1,91 +0,0 @@ -use crate::Entry; -use sha2::{Digest, Sha256}; -use std::{ - error::Error, - ffi::OsStr, - fmt::Write, - fs, - io::Read, - os::unix::fs::MetadataExt, - path::{Path, PathBuf}, -}; -use crate::tar::{Node, Owner}; - -#[derive(Clone, Debug)] -pub struct Item { - pub entry: Entry, - pub data: Vec, -} - -impl Item { - pub fn try_create(path: &Path) -> Result> { - let path = fix_path(path); - let meta = fs::metadata(&path)?; - let filename = format!("{}", path.display()); - let owner = Some(Owner::default()); - if meta.is_file() { - let mut data = vec![]; - let mut fd = fs::File::open(path)?; - let path = PathBuf::from(&filename); - let size = fd.read_to_end(&mut data)?; - let mut sha256sum = String::new(); - let mut hasher = Sha256::new(); - hasher.update(&data); - let res = hasher.finalize(); - for c in res { - write!(sha256sum, "{c:02x}")?; - } - let mode = meta.mode(); - Ok(Self { - entry: Entry::File { - path, - sha256sum, - mode, - size, - }, - data: Node::read_data_to_tar(&data, &filename, &meta, owner)?.to_vec()?, - }) - } else if meta.is_dir() { - let mode = meta.mode(); - let path = PathBuf::from(&filename); - Ok(Self { - entry: Entry::Directory { path, mode }, - data: Node::read_data_to_tar(&[0; 0], &filename, &meta, owner)?.to_vec()?, - }) - } else if meta.is_symlink() { - let target = fs::read_link(path)?; - let path = PathBuf::from(&filename); - Ok(Self { - entry: Entry::Link { path, target }, - data: Node::read_data_to_tar(&[0; 0], &filename, &meta, owner)?.to_vec()?, - }) - } else { - unreachable!(); - } - } -} - -fn fix_path(path: &Path) -> PathBuf { - let path = if let Ok(p) = path.strip_prefix("./") { - p - } else { - path - }; - if path.is_file() || path.is_symlink() { - match path.ancestors().last().and_then(Path::to_str) { - Some("etc" | "var") => { - let ext = if let Some(x) = path.extension().and_then(OsStr::to_str) { - format!("{x}.new") - } else { - "new".to_string() - }; - let mut path = path.to_path_buf(); - path.set_extension(ext); - path - } - _ => path.to_path_buf(), - } - } else { - path.to_path_buf() - } -} diff --git a/src/lib.rs b/src/lib.rs index ea6d0ff..6dd6e1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,9 @@ pub mod tar; -mod creator; -mod item; mod package; mod plist; mod version; pub use { - creator::{Creator, Message}, - item::Item, package::{Dependency, Package, Specs}, plist::*, version::*, diff --git a/src/package/mod.rs b/src/package/mod.rs index 13bde79..c706274 100644 --- a/src/package/mod.rs +++ b/src/package/mod.rs @@ -85,7 +85,7 @@ impl Package { to_string_pretty(self, cfg) } - pub(crate) fn save_ron_and_create_tar_node( + pub fn save_ron_and_create_tar_node( &self, outdir: &Path, ) -> Result> { diff --git a/test/1.tar b/test/1.tar new file mode 100644 index 0000000..ef16843 Binary files /dev/null and b/test/1.tar differ diff --git a/test/1.txt b/test/1.txt new file mode 100644 index 0000000..6de7b8c --- /dev/null +++ b/test/1.txt @@ -0,0 +1 @@ +This is a test file. diff --git a/test/2.tar b/test/2.tar new file mode 100644 index 0000000..3e7ac15 Binary files /dev/null and b/test/2.tar differ