Add --quiet option to repak_cli

This commit is contained in:
Truman Kilen 2024-01-06 17:43:50 -06:00
parent 032dbcaa0b
commit 7b647d9179
2 changed files with 62 additions and 17 deletions

View file

@ -23,6 +23,7 @@ path-slash = "0.2.1"
rayon = "1.6.1" rayon = "1.6.1"
sha2 = "0.10.7" sha2 = "0.10.7"
strum = { workspace = true } strum = { workspace = true }
itertools = "0.12.0"
[dev-dependencies] [dev-dependencies]
assert_cmd = "2.0.12" assert_cmd = "2.0.12"

View file

@ -57,6 +57,10 @@ struct ActionUnpack {
#[arg(short, long, default_value = "false")] #[arg(short, long, default_value = "false")]
verbose: bool, verbose: bool,
/// Hides normal output such as progress bar and completion status
#[arg(short, long, default_value = "false")]
quiet: bool,
/// Force overwrite existing files/directories. /// Force overwrite existing files/directories.
#[arg(short, long, default_value = "false")] #[arg(short, long, default_value = "false")]
force: bool, force: bool,
@ -95,6 +99,10 @@ struct ActionPack {
/// Verbose /// Verbose
#[arg(short, long, default_value = "false")] #[arg(short, long, default_value = "false")]
verbose: bool, verbose: bool,
/// Hides normal output such as progress bar and completion status
#[arg(short, long, default_value = "false")]
quiet: bool,
} }
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@ -280,6 +288,20 @@ 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})";
#[derive(Clone)]
enum Output {
Progress(indicatif::ProgressBar),
Stdout,
}
impl Output {
pub fn println<I: AsRef<str>>(&self, msg: I) {
match self {
Output::Progress(progress) => progress.println(msg),
Output::Stdout => println!("{}", msg.as_ref()),
}
}
}
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 { for input in &action.input {
let mut builder = repak::PakBuilder::new().oodle(oodle_loader::decompress); let mut builder = repak::PakBuilder::new().oodle(oodle_loader::decompress);
@ -355,14 +377,20 @@ fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repa
.filter_map(|e| e.transpose()) .filter_map(|e| e.transpose())
.collect::<Result<Vec<_>, repak::Error>>()?; .collect::<Result<Vec<_>, repak::Error>>()?;
let progress = indicatif::ProgressBar::new(entries.len() as u64) let progress = (!action.quiet).then(|| {
.with_style(indicatif::ProgressStyle::with_template(STYLE).unwrap()); indicatif::ProgressBar::new(entries.len() as u64)
.with_style(indicatif::ProgressStyle::with_template(STYLE).unwrap())
});
let log = match &progress {
Some(progress) => Output::Progress(progress.clone()),
None => Output::Stdout,
};
entries.par_iter().try_for_each_init( entries.par_iter().try_for_each_init(
|| (progress.clone(), File::open(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)); log.println(format!("unpacking {}", entry.entry_path));
} }
fs::create_dir_all(&entry.out_dir)?; fs::create_dir_all(&entry.out_dir)?;
pak.read_file( pak.read_file(
@ -373,18 +401,24 @@ fn unpack(aes_key: Option<aes::Aes256>, action: ActionUnpack) -> Result<(), repa
), ),
&mut fs::File::create(&entry.out_path)?, &mut fs::File::create(&entry.out_path)?,
)?; )?;
progress.inc(1); if let Some(progress) = progress {
progress.inc(1);
}
Ok(()) Ok(())
}, },
)?; )?;
progress.finish(); if let Some(progress) = progress {
progress.finish();
}
println!( if !action.quiet {
"Unpacked {} files to {} from {}", println!(
entries.len(), "Unpacked {} files to {} from {}",
output.display(), entries.len(),
input output.display(),
); input
);
}
} }
Ok(()) Ok(())
@ -428,10 +462,18 @@ fn pack(args: ActionPack) -> Result<(), repak::Error> {
use indicatif::ProgressIterator; use indicatif::ProgressIterator;
let mut iter = paths let iter = paths.iter();
.iter() let (log, mut iter) = if !args.quiet {
.progress_with_style(indicatif::ProgressStyle::with_template(STYLE).unwrap()); let iter =
let progress = iter.progress.clone(); iter.progress_with_style(indicatif::ProgressStyle::with_template(STYLE).unwrap());
(
Output::Progress(iter.progress.clone()),
itertools::Either::Left(iter),
)
} else {
(Output::Stdout, itertools::Either::Right(iter))
};
let log = log.clone();
iter.try_for_each(|p| { iter.try_for_each(|p| {
let rel = &p let rel = &p
.strip_prefix(input_path) .strip_prefix(input_path)
@ -439,14 +481,16 @@ fn pack(args: ActionPack) -> Result<(), repak::Error> {
.to_slash() .to_slash()
.expect("failed to convert to slash path"); .expect("failed to convert to slash path");
if args.verbose { if args.verbose {
progress.println(format!("packing {}", &rel)); log.println(format!("packing {}", &rel));
} }
pak.write_file(rel, std::fs::read(p)?) pak.write_file(rel, std::fs::read(p)?)
})?; })?;
pak.write_index()?; pak.write_index()?;
println!("Packed {} files to {}", paths.len(), output.display()); if !args.quiet {
println!("Packed {} files to {}", paths.len(), output.display());
}
Ok(()) Ok(())
} }