From 420610297fcc8c82c6afd886cc65492ea587964c Mon Sep 17 00:00:00 2001 From: sokorototo Date: Sat, 30 Mar 2024 00:37:48 +0300 Subject: [PATCH] added some missing documentation, minimal CLI changes --- vach-cli/README.md | 30 +++++--- vach-cli/src/commands/list.rs | 125 ++++++++++++++-------------------- vach-cli/src/commands/pack.rs | 39 +++++------ 3 files changed, 87 insertions(+), 107 deletions(-) diff --git a/vach-cli/README.md b/vach-cli/README.md index 55e48fdd..eb36241e 100644 --- a/vach-cli/README.md +++ b/vach-cli/README.md @@ -63,9 +63,8 @@ vach list -i textures.vach > `pack` is used to pack files and directories into archives. It takes inputs for customizing how the archive should be packaged. ```sh -# The simplest pack command. # Any pack command must have an output, set using the "-o" or "--output" keys -# This builds only an empty archive +# This builds an empty archive vach pack -o hello.vach # You can add files as inputs using the "-i" or "--input" keys @@ -127,10 +126,9 @@ vach pack -t -o hello.vach -i hello.txt goodbye.txt ### 2: unpack ->`unpack` is used to unpack archives back into their constituent files. +>`unpack` it's just like `pack` but backwards ```sh -# The simplest unpack command # Provide an input: "-i" or "--input" vach unpack -i target.vach @@ -151,12 +149,26 @@ vach unpack -k keypair.kp -i source.vach vach unpack -s keypair.sk -i source.vach ``` -### 3: list +### 3: pipe + +>`pipe`: Read the data from a _specific_ entry and pipe it to stdout + +```sh +# Print to stdout +vach pipe -i target.vach -r npc-dialogue.txt + +# Pipe directly into a file +vach pipe -i target.vach -r npc-dialogue.txt >> npc-dialogue.txt + +# Pipe into another process' stdin +vach pipe -i presets.vach -r low.json | jq '."TextureResolution"' +``` + +### 4: list > Lists all the entries in the archive as a table ```sh -# The simplest list command # Provide some input: "-i" or "--input" vach list -i textures.vach @@ -170,7 +182,7 @@ vach list -i textures.vach -m TXTRS vach list -i textures.vach -m TXTRS --sort size-descending ``` -### 4: verify +### 5: verify > Verifies the validity of a file as an archive @@ -182,7 +194,7 @@ vach verify -i textures.vach vach verify -i textures.vach -m TXTRS ``` -### 5: keypair +### 6: keypair > Key-pair generation command @@ -197,7 +209,7 @@ vach keypair -s -o keypair.kp # -> keypair.sk ``` -### 6: split +### 7: split > Splits an existing keypair into it's public and secret components diff --git a/vach-cli/src/commands/list.rs b/vach-cli/src/commands/list.rs index 6be3810f..a62a1b38 100644 --- a/vach-cli/src/commands/list.rs +++ b/vach-cli/src/commands/list.rs @@ -6,22 +6,14 @@ use tabled::{ }; use vach::{ prelude::{ArchiveConfig, Archive, Flags}, - archive::{CompressionAlgorithm, RegistryEntry}, + archive::RegistryEntry, }; use indicatif::HumanBytes; use super::CommandTrait; use crate::keys::key_names; -pub const VERSION: &str = "0.2.0"; - -enum Sort { - SizeAscending, - SizeDescending, - Alphabetical, - AlphabeticalReversed, - None, -} +pub const VERSION: &str = "0.2.1"; /// This command lists the entries in an archive in tabulated form pub struct Evaluator; @@ -35,15 +27,6 @@ impl CommandTrait for Evaluator { }, }; - let sort = match args.value_of(key_names::SORT) { - Some("alphabetical") => Sort::Alphabetical, - Some("alphabetical-reversed") => Sort::AlphabeticalReversed, - Some("size-ascending") => Sort::SizeAscending, - Some("size-descending") => Sort::SizeDescending, - Some(sort) => anyhow::bail!("Unknown sort given: {}. Valid sort types are: 'alphabetical' 'alphabetical-descending' 'size-ascending' 'size-descending'", sort), - None => Sort::None, - }; - let magic: [u8; vach::MAGIC_LENGTH] = match args.value_of(key_names::MAGIC) { Some(magic) => magic.as_bytes().try_into()?, None => *vach::DEFAULT_MAGIC, @@ -52,61 +35,53 @@ impl CommandTrait for Evaluator { let file = File::open(archive_path)?; let archive = Archive::with_config(file, &ArchiveConfig::new(magic, None))?; - if archive.entries().is_empty() { - println!("{}", archive); - } else { - let mut entries: Vec<(String, RegistryEntry)> = archive - .entries() - .iter() - .map(|(id, entry)| (id.clone(), entry.clone())) - .collect(); - - // Log some additional info about this archive - println!("{}", archive); - - // Sort the entries accordingly - match sort { - Sort::SizeAscending => entries.sort_by(|a, b| a.1.offset.cmp(&b.1.offset)), - Sort::SizeDescending => entries.sort_by(|a, b| b.1.offset.cmp(&a.1.offset)), - Sort::Alphabetical => entries.sort_by(|a, b| a.0.cmp(&b.0)), - Sort::AlphabeticalReversed => entries.sort_by(|a, b| b.0.cmp(&a.0)), - Sort::None => (), - }; - - let table_entries: Vec = entries - .iter() - .map(|(id, entry)| { - let c_algo = if entry.flags.contains(Flags::LZ4_COMPRESSED) { - Some(CompressionAlgorithm::LZ4) - } else if entry.flags.contains(Flags::BROTLI_COMPRESSED) { - Some(CompressionAlgorithm::Brotli(8)) - } else if entry.flags.contains(Flags::SNAPPY_COMPRESSED) { - Some(CompressionAlgorithm::Snappy) - } else { - None - }; - - let c_algo = match c_algo { - Some(algo) => algo.to_string(), - None => "None".to_string(), - }; - - FileTableEntry { - id, - size: HumanBytes(entry.offset).to_string(), - flags: entry.flags, - compression: c_algo, - } - }) - .collect(); - - let mut table = Table::new(table_entries); - table - .with(Style::rounded()) - .with(Modify::list(Columns::new(..1), Alignment::left())); - - println!("{}", table); - } + // log basic metadata + println!("{}", archive); + + let mut entries: Vec<(String, RegistryEntry)> = archive + .entries() + .iter() + .map(|(id, entry)| (id.clone(), entry.clone())) + .collect(); + + // Sort the entries accordingly + match args.value_of(key_names::SORT) { + Some("alphabetical") => entries.sort_by(|a, b| a.0.cmp(&b.0)), + Some("alphabetical-reversed") => entries.sort_by(|a, b| b.0.cmp(&a.0)), + Some("size-ascending") => entries.sort_by(|a, b| a.1.offset.cmp(&b.1.offset)), + Some("size-descending") => entries.sort_by(|a, b| b.1.offset.cmp(&a.1.offset)), + Some(sort) => anyhow::bail!("Unknown sort option provided: {}. Valid sort types are: 'alphabetical' 'alphabetical-descending' 'size-ascending' 'size-descending'", sort), + _ => (), + }; + + let table_entries: Vec = entries + .iter() + .map(|(id, entry)| { + let c_algo = if entry.flags.contains(Flags::LZ4_COMPRESSED) { + "LZ4" + } else if entry.flags.contains(Flags::BROTLI_COMPRESSED) { + "Brotli" + } else if entry.flags.contains(Flags::SNAPPY_COMPRESSED) { + "Snappy" + } else { + "None" + }; + + FileTableEntry { + id, + size: HumanBytes(entry.offset).to_string(), + flags: entry.flags, + compression: c_algo, + } + }) + .collect(); + + let mut table = Table::new(table_entries); + table + .with(Style::rounded()) + .with(Modify::list(Columns::new(..1), Alignment::left())); + + println!("{}", table); Ok(()) } @@ -117,5 +92,5 @@ struct FileTableEntry<'a> { id: &'a str, size: String, flags: Flags, - compression: String, + compression: &'static str, } diff --git a/vach-cli/src/commands/pack.rs b/vach-cli/src/commands/pack.rs index e0a5c3d3..086ba29b 100644 --- a/vach-cli/src/commands/pack.rs +++ b/vach-cli/src/commands/pack.rs @@ -30,8 +30,8 @@ impl Read for FileWrapper { }; let result = file.read(buf); - // Intercepts a file once it's finished reading to drop it, thus avoiding OS filesystem limitations easily - // Meaning we can safely drop the `fs::File` stored in this file wrapper + // Once the file is done reading, we drop the file handle + // TOo avoid hitting OS limitations if let Ok(0) = result { self.1.take(); }; @@ -107,7 +107,7 @@ impl CommandTrait for Evaluator { }; // Extract the inputs - let mut inputs: Vec = vec![]; + let mut inputs = vec![]; // Used to filter invalid inputs and excluded inputs let path_filter = |path: &PathBuf| match path.canonicalize() { @@ -188,8 +188,8 @@ impl CommandTrait for Evaluator { kp = Some(generated); } - let pbar = ProgressBar::new(inputs.len() as u64 + 5 + if truncate { 3 } else { 0 }); - pbar.set_style( + let progress = ProgressBar::new(inputs.len() as u64 + 5 + if truncate { 3 } else { 0 }); + progress.set_style( ProgressStyle::default_bar() .template(super::PROGRESS_BAR_STYLE)? .progress_chars("█░-") @@ -198,8 +198,8 @@ impl CommandTrait for Evaluator { // Since it wraps it's internal state in an arc, we can safely clone and send across threads let callback = |leaf: &Leaf, _: &RegistryEntry| { - pbar.inc(1); - pbar.set_message(leaf.id.clone()) + progress.inc(1); + progress.set_message(leaf.id.clone()) }; // Build a builder-config using the above extracted data @@ -234,42 +234,35 @@ impl CommandTrait for Evaluator { // Process the files for wrapper in &mut inputs { if !wrapper.0.exists() { - pbar.println(format!("Skipping {}, does not exist!", wrapper.0.to_string_lossy())); - - pbar.inc(1); + println!("Skipping {}, does not exist!", wrapper.0.to_string_lossy()); + progress.inc(1); continue; } - let id = wrapper - .0 - .to_string_lossy() - .trim_start_matches("./") - .trim_start_matches(".\\") - .to_string(); - println!("Preparing {} for packaging", id); + let id = wrapper.0.to_string_lossy().into_owned(); builder.add(wrapper, &id)?; } // Inform of success in input queue - pbar.inc(2); + progress.inc(2); builder.dump(output_file, &builder_config)?; - pbar.println(format!("Generated a new archive @ {}", output_path)); + progress.println(format!("Generated a new archive @ {}", output_path)); drop(builder); // Truncate original files if truncate { for wrapper in inputs { std::fs::remove_file(&wrapper.0)?; - pbar.finish(); - pbar.println(format!("Truncated original file @ {}", wrapper.0.to_string_lossy())); + progress.println(format!("Truncated original file @ {}", wrapper.0.to_string_lossy())); } - pbar.inc(3); + progress.inc(3); }; - pbar.inc(3); + progress.inc(3); + progress.finish(); Ok(()) }