Allow unpack to accept multiple paks; resolves #10

This commit is contained in:
Truman Kilen 2023-09-17 17:46:27 -05:00
parent 720222ba39
commit 9c9be74946

View file

@ -43,10 +43,10 @@ struct ActionHashList {
struct ActionUnpack { struct ActionUnpack {
/// Input .pak path /// Input .pak path
#[arg(index = 1)] #[arg(index = 1)]
input: String, input: Vec<String>,
/// Output directory. Defaults to next to input pak /// Output directory. Defaults to next to input pak
#[arg(index = 2)] #[arg(short, long)]
output: Option<String>, output: Option<String>,
/// Prefix to strip from entry path /// Prefix to strip from entry path
@ -279,20 +279,26 @@ fn hash_list(aes_key: Option<aes::Aes256>, action: ActionHashList) -> Result<(),
const STYLE: &str = "[{elapsed_precise}] [{wide_bar}] {pos}/{len} ({eta})"; const STYLE: &str = "[{elapsed_precise}] [{wide_bar}] {pos}/{len} ({eta})";
fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repak::Error> { fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repak::Error> {
for input in &action.input {
let pak = repak::PakReader::new_any_with_optional_key( let pak = repak::PakReader::new_any_with_optional_key(
&mut BufReader::new(File::open(&action.input)?), &mut BufReader::new(File::open(input)?),
aes_key, aes_key.clone(),
)?; )?;
let output = action let output = action
.output .output
.as_ref()
.map(PathBuf::from) .map(PathBuf::from)
.unwrap_or_else(|| Path::new(&action.input).with_extension("")); .unwrap_or_else(|| Path::new(input).with_extension(""));
match fs::create_dir(&output) { match fs::create_dir(&output) {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(ref e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()), Err(ref e)
if action.output.is_some() && e.kind() == std::io::ErrorKind::AlreadyExists =>
{
Ok(())
}
Err(e) => Err(e), Err(e) => Err(e),
}?; }?;
if !action.force && output.read_dir()?.next().is_some() { if action.output.is_none() && !action.force && output.read_dir()?.next().is_some() {
return Err(repak::Error::OutputNotEmpty( return Err(repak::Error::OutputNotEmpty(
output.to_string_lossy().to_string(), output.to_string_lossy().to_string(),
)); ));
@ -312,8 +318,8 @@ fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repa
out_dir: PathBuf, out_dir: PathBuf,
} }
let entries = let entries = pak
pak.files() .files()
.into_iter() .into_iter()
.map(|entry_path| { .map(|entry_path| {
let full_path = mount_point.join(&entry_path); let full_path = mount_point.join(&entry_path);
@ -349,7 +355,7 @@ fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repa
let progress = indicatif::ProgressBar::new(entries.len() as u64) let progress = indicatif::ProgressBar::new(entries.len() as u64)
.with_style(indicatif::ProgressStyle::with_template(STYLE).unwrap()); .with_style(indicatif::ProgressStyle::with_template(STYLE).unwrap());
entries.par_iter().try_for_each_init( entries.par_iter().try_for_each_init(
|| (progress.clone(), File::open(&action.input)), || (progress.clone(), File::open(input)),
|(progress, file), entry| -> Result<(), repak::Error> { |(progress, file), entry| -> Result<(), repak::Error> {
if action.verbose { if action.verbose {
progress.println(format!("unpacking {}", entry.entry_path)); progress.println(format!("unpacking {}", entry.entry_path));
@ -366,7 +372,13 @@ fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repa
)?; )?;
progress.finish(); progress.finish();
println!("Unpacked {} files to {}", entries.len(), output.display()); println!(
"Unpacked {} files to {} from {}",
entries.len(),
output.display(),
input
);
}
Ok(()) Ok(())
} }