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
|
/target
|
||||||
/Cargo.lock
|
/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;
|
pub mod tar;
|
||||||
mod creator;
|
|
||||||
mod item;
|
|
||||||
mod package;
|
mod package;
|
||||||
mod plist;
|
mod plist;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
pub use {
|
pub use {
|
||||||
creator::{Creator, Message},
|
|
||||||
item::Item,
|
|
||||||
package::{Dependency, Package, Specs},
|
package::{Dependency, Package, Specs},
|
||||||
plist::*,
|
plist::*,
|
||||||
version::*,
|
version::*,
|
||||||
|
@ -85,7 +85,7 @@ impl Package {
|
|||||||
to_string_pretty(self, cfg)
|
to_string_pretty(self, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn save_ron_and_create_tar_node(
|
pub fn save_ron_and_create_tar_node(
|
||||||
&self,
|
&self,
|
||||||
outdir: &Path,
|
outdir: &Path,
|
||||||
) -> Result<Node, Box<dyn Error>> {
|
) -> 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