Add minitar test files; Remove creator and item modules;
This commit is contained in:
parent
1e7d73bc28
commit
ee52bfb462
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
test
|
||||
tags
|
||||
|
@ -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<PathBuf>,
|
||||
specs: Specs,
|
||||
}
|
||||
|
||||
impl Creator {
|
||||
pub fn new(path: &Path, specs: Specs) -> Result<Self, io::Error> {
|
||||
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::<Vec<_>>();
|
||||
env::set_current_dir(d)?;
|
||||
Ok(Self {
|
||||
path,
|
||||
entries,
|
||||
specs,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn from_list(list: &[&str], specs: Specs) -> Result<Self, io::Error> {
|
||||
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<Message>) -> Result<(), Box<dyn Error>> {
|
||||
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(())
|
||||
}
|
||||
}
|
@ -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<u8>,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
pub fn try_create(path: &Path) -> Result<Self, Box<dyn Error>> {
|
||||
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()
|
||||
}
|
||||
}
|
@ -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::*,
|
||||
|
@ -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<Node, Box<dyn Error>> {
|
||||
|
BIN
test/1.tar
Normal file
BIN
test/1.tar
Normal file
Binary file not shown.
1
test/1.txt
Normal file
1
test/1.txt
Normal file
@ -0,0 +1 @@
|
||||
This is a test file.
|
BIN
test/2.tar
Normal file
BIN
test/2.tar
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user