mirror of
https://github.com/BLAKE3-team/BLAKE3
synced 2024-05-26 11:46:04 +02:00
Generate `b3sum(1)` at build time
This commit is contained in:
parent
0816badf3a
commit
7f2e247f55
|
@ -75,6 +75,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"blake3",
|
"blake3",
|
||||||
"clap",
|
"clap",
|
||||||
|
"clap_mangen",
|
||||||
"duct",
|
"duct",
|
||||||
"hex",
|
"hex",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
@ -154,6 +155,16 @@ version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_mangen"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e1dd95b5ebb5c1c54581dd6346f3ed6a79a3eef95dd372fc2ac13d535535300e"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"roff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -318,6 +329,12 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roff"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.31"
|
version = "0.38.31"
|
||||||
|
|
|
@ -24,3 +24,8 @@ wild = "2.0.3"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
duct = "0.13.3"
|
duct = "0.13.3"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
blake3 = { version = "1", path = ".." }
|
||||||
|
clap = { version = "4.0.8", features = ["derive"] }
|
||||||
|
clap_mangen = "0.2.20"
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
use clap::CommandFactory;
|
||||||
|
|
||||||
|
include!("src/cli.rs");
|
||||||
|
|
||||||
|
fn generate_man_page(out_dir: &std::path::Path) -> std::io::Result<()> {
|
||||||
|
let command = Inner::command();
|
||||||
|
|
||||||
|
let man = clap_mangen::Man::new(command).date("2024-04-24");
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
man.render_title(&mut buf)?;
|
||||||
|
|
||||||
|
// The NAME section.
|
||||||
|
let mut roff = clap_mangen::roff::Roff::new();
|
||||||
|
roff.control("SH", ["NAME"]);
|
||||||
|
roff.text([clap_mangen::roff::roman(
|
||||||
|
"b3sum - compute and check BLAKE3 message digest",
|
||||||
|
)]);
|
||||||
|
roff.to_writer(&mut buf)?;
|
||||||
|
|
||||||
|
// The SYNOPSIS section.
|
||||||
|
let mut roff = clap_mangen::roff::Roff::new();
|
||||||
|
roff.control("SH", ["SYNOPSIS"]);
|
||||||
|
roff.text([
|
||||||
|
clap_mangen::roff::bold("b3sum"),
|
||||||
|
clap_mangen::roff::roman(" ["),
|
||||||
|
clap_mangen::roff::italic("OPTIONS"),
|
||||||
|
clap_mangen::roff::roman("] ["),
|
||||||
|
clap_mangen::roff::italic("FILE"),
|
||||||
|
clap_mangen::roff::roman("]..."),
|
||||||
|
]);
|
||||||
|
roff.to_writer(&mut buf)?;
|
||||||
|
|
||||||
|
man.render_description_section(&mut buf)?;
|
||||||
|
man.render_options_section(&mut buf)?;
|
||||||
|
|
||||||
|
// The SEE ALSO section.
|
||||||
|
let mut roff = clap_mangen::roff::Roff::new();
|
||||||
|
roff.control("SH", ["SEE ALSO"]);
|
||||||
|
roff.text([
|
||||||
|
clap_mangen::roff::bold("b2sum"),
|
||||||
|
clap_mangen::roff::roman("(1), "),
|
||||||
|
clap_mangen::roff::bold("md5sum"),
|
||||||
|
clap_mangen::roff::roman("(1)"),
|
||||||
|
]);
|
||||||
|
roff.to_writer(&mut buf)?;
|
||||||
|
|
||||||
|
std::fs::write(out_dir.join("b3sum.1"), buf)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
println!("cargo:rerun-if-changed=src/cli.rs");
|
||||||
|
|
||||||
|
let out_dir = std::env::var("OUT_DIR").expect("environment variable `OUT_DIR` not defined");
|
||||||
|
let out_dir = std::path::PathBuf::from(out_dir);
|
||||||
|
|
||||||
|
generate_man_page(&out_dir)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
use clap::Parser;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
const DERIVE_KEY_ARG: &str = "derive_key";
|
||||||
|
const KEYED_ARG: &str = "keyed";
|
||||||
|
const LENGTH_ARG: &str = "length";
|
||||||
|
const NO_NAMES_ARG: &str = "no_names";
|
||||||
|
const RAW_ARG: &str = "raw";
|
||||||
|
const CHECK_ARG: &str = "check";
|
||||||
|
|
||||||
|
/// Print or check BLAKE3 checksums.
|
||||||
|
///
|
||||||
|
/// With no FILE, or when FILE is -, read standard input.
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(version, max_term_width(100))]
|
||||||
|
pub struct Inner {
|
||||||
|
/// Files to hash, or checkfiles to check
|
||||||
|
///
|
||||||
|
/// When no file is given, or when - is given, read standard input.
|
||||||
|
pub file: Vec<PathBuf>,
|
||||||
|
|
||||||
|
/// Use the keyed mode, reading the 32-byte key from stdin
|
||||||
|
#[arg(long, requires("file"))]
|
||||||
|
pub keyed: bool,
|
||||||
|
|
||||||
|
/// Use the key derivation mode, with the given context string
|
||||||
|
///
|
||||||
|
/// Cannot be used with --keyed.
|
||||||
|
#[arg(long, value_name("CONTEXT"), conflicts_with(KEYED_ARG))]
|
||||||
|
pub derive_key: Option<String>,
|
||||||
|
|
||||||
|
/// The number of output bytes, before hex encoding
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
default_value_t = blake3::OUT_LEN as u64,
|
||||||
|
value_name("LEN")
|
||||||
|
)]
|
||||||
|
pub length: u64,
|
||||||
|
|
||||||
|
/// The starting output byte offset, before hex encoding
|
||||||
|
#[arg(long, default_value_t = 0, value_name("SEEK"))]
|
||||||
|
pub seek: u64,
|
||||||
|
|
||||||
|
/// The maximum number of threads to use
|
||||||
|
///
|
||||||
|
/// By default, this is the number of logical cores. If this flag is
|
||||||
|
/// omitted, or if its value is 0, RAYON_NUM_THREADS is also respected.
|
||||||
|
#[arg(long, value_name("NUM"))]
|
||||||
|
pub num_threads: Option<usize>,
|
||||||
|
|
||||||
|
/// Disable memory mapping
|
||||||
|
///
|
||||||
|
/// Currently this also disables multithreading.
|
||||||
|
#[arg(long)]
|
||||||
|
pub no_mmap: bool,
|
||||||
|
|
||||||
|
/// Omit filenames in the output
|
||||||
|
#[arg(long)]
|
||||||
|
pub no_names: bool,
|
||||||
|
|
||||||
|
/// Write raw output bytes to stdout, rather than hex
|
||||||
|
///
|
||||||
|
/// --no-names is implied. In this case, only a single input is allowed.
|
||||||
|
#[arg(long)]
|
||||||
|
pub raw: bool,
|
||||||
|
|
||||||
|
/// Read BLAKE3 sums from the [FILE]s and check them
|
||||||
|
#[arg(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
conflicts_with(DERIVE_KEY_ARG),
|
||||||
|
conflicts_with(KEYED_ARG),
|
||||||
|
conflicts_with(LENGTH_ARG),
|
||||||
|
conflicts_with(RAW_ARG),
|
||||||
|
conflicts_with(NO_NAMES_ARG)
|
||||||
|
)]
|
||||||
|
pub check: bool,
|
||||||
|
|
||||||
|
/// Skip printing OK for each checked file
|
||||||
|
///
|
||||||
|
/// Must be used with --check.
|
||||||
|
#[arg(long, requires(CHECK_ARG))]
|
||||||
|
pub quiet: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use clap::CommandFactory;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_args() {
|
||||||
|
Inner::command().debug_assert();
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,93 +6,15 @@ use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
mod cli;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod unit_tests;
|
mod unit_tests;
|
||||||
|
|
||||||
const NAME: &str = "b3sum";
|
const NAME: &str = "b3sum";
|
||||||
|
|
||||||
const DERIVE_KEY_ARG: &str = "derive_key";
|
|
||||||
const KEYED_ARG: &str = "keyed";
|
|
||||||
const LENGTH_ARG: &str = "length";
|
|
||||||
const NO_NAMES_ARG: &str = "no_names";
|
|
||||||
const RAW_ARG: &str = "raw";
|
|
||||||
const CHECK_ARG: &str = "check";
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
|
||||||
#[command(version, max_term_width(100))]
|
|
||||||
struct Inner {
|
|
||||||
/// Files to hash, or checkfiles to check
|
|
||||||
///
|
|
||||||
/// When no file is given, or when - is given, read standard input.
|
|
||||||
file: Vec<PathBuf>,
|
|
||||||
|
|
||||||
/// Use the keyed mode, reading the 32-byte key from stdin
|
|
||||||
#[arg(long, requires("file"))]
|
|
||||||
keyed: bool,
|
|
||||||
|
|
||||||
/// Use the key derivation mode, with the given context string
|
|
||||||
///
|
|
||||||
/// Cannot be used with --keyed.
|
|
||||||
#[arg(long, value_name("CONTEXT"), conflicts_with(KEYED_ARG))]
|
|
||||||
derive_key: Option<String>,
|
|
||||||
|
|
||||||
/// The number of output bytes, before hex encoding
|
|
||||||
#[arg(
|
|
||||||
short,
|
|
||||||
long,
|
|
||||||
default_value_t = blake3::OUT_LEN as u64,
|
|
||||||
value_name("LEN")
|
|
||||||
)]
|
|
||||||
length: u64,
|
|
||||||
|
|
||||||
/// The starting output byte offset, before hex encoding
|
|
||||||
#[arg(long, default_value_t = 0, value_name("SEEK"))]
|
|
||||||
seek: u64,
|
|
||||||
|
|
||||||
/// The maximum number of threads to use
|
|
||||||
///
|
|
||||||
/// By default, this is the number of logical cores. If this flag is
|
|
||||||
/// omitted, or if its value is 0, RAYON_NUM_THREADS is also respected.
|
|
||||||
#[arg(long, value_name("NUM"))]
|
|
||||||
num_threads: Option<usize>,
|
|
||||||
|
|
||||||
/// Disable memory mapping
|
|
||||||
///
|
|
||||||
/// Currently this also disables multithreading.
|
|
||||||
#[arg(long)]
|
|
||||||
no_mmap: bool,
|
|
||||||
|
|
||||||
/// Omit filenames in the output
|
|
||||||
#[arg(long)]
|
|
||||||
no_names: bool,
|
|
||||||
|
|
||||||
/// Write raw output bytes to stdout, rather than hex
|
|
||||||
///
|
|
||||||
/// --no-names is implied. In this case, only a single input is allowed.
|
|
||||||
#[arg(long)]
|
|
||||||
raw: bool,
|
|
||||||
|
|
||||||
/// Read BLAKE3 sums from the [FILE]s and check them
|
|
||||||
#[arg(
|
|
||||||
short,
|
|
||||||
long,
|
|
||||||
conflicts_with(DERIVE_KEY_ARG),
|
|
||||||
conflicts_with(KEYED_ARG),
|
|
||||||
conflicts_with(LENGTH_ARG),
|
|
||||||
conflicts_with(RAW_ARG),
|
|
||||||
conflicts_with(NO_NAMES_ARG)
|
|
||||||
)]
|
|
||||||
check: bool,
|
|
||||||
|
|
||||||
/// Skip printing OK for each checked file
|
|
||||||
///
|
|
||||||
/// Must be used with --check.
|
|
||||||
#[arg(long, requires(CHECK_ARG))]
|
|
||||||
quiet: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Args {
|
struct Args {
|
||||||
inner: Inner,
|
inner: crate::cli::Inner,
|
||||||
file_args: Vec<PathBuf>,
|
file_args: Vec<PathBuf>,
|
||||||
base_hasher: blake3::Hasher,
|
base_hasher: blake3::Hasher,
|
||||||
}
|
}
|
||||||
|
@ -101,7 +23,7 @@ impl Args {
|
||||||
fn parse() -> Result<Self> {
|
fn parse() -> Result<Self> {
|
||||||
// wild::args_os() is equivalent to std::env::args_os() on Unix,
|
// wild::args_os() is equivalent to std::env::args_os() on Unix,
|
||||||
// but on Windows it adds support for globbing.
|
// but on Windows it adds support for globbing.
|
||||||
let inner = Inner::parse_from(wild::args_os());
|
let inner = crate::cli::Inner::parse_from(wild::args_os());
|
||||||
let file_args = if !inner.file.is_empty() {
|
let file_args = if !inner.file.is_empty() {
|
||||||
inner.file.clone()
|
inner.file.clone()
|
||||||
} else {
|
} else {
|
||||||
|
@ -509,13 +431,3 @@ fn main() -> Result<()> {
|
||||||
std::process::exit(if files_failed > 0 { 1 } else { 0 });
|
std::process::exit(if files_failed > 0 { 1 } else { 0 });
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use clap::CommandFactory;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_args() {
|
|
||||||
crate::Inner::command().debug_assert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue