diff options
-rw-r--r-- | Cargo.lock | 101 | ||||
-rw-r--r-- | sq/Cargo.toml | 5 | ||||
-rw-r--r-- | sq/build.rs | 13 | ||||
-rw-r--r-- | sq/src/commands/autocrypt.rs | 4 | ||||
-rw-r--r-- | sq/src/commands/key.rs | 10 | ||||
-rw-r--r-- | sq/src/commands/keyring.rs | 10 | ||||
-rw-r--r-- | sq/src/commands/net.rs | 10 | ||||
-rw-r--r-- | sq/src/commands/revoke.rs | 6 | ||||
-rw-r--r-- | sq/src/sq-usage.rs | 1154 | ||||
-rw-r--r-- | sq/src/sq.rs | 38 | ||||
-rw-r--r-- | sq/src/sq_cli.rs | 678 |
11 files changed, 1029 insertions, 1000 deletions
@@ -414,14 +414,62 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", - "term_size", + "strsim 0.8.0", "textwrap 0.11.0", "unicode-width", "vec_map", ] [[package]] +name = "clap" +version = "3.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47582c09be7c8b32c0ab3a6181825ababb713fde6fff20fc573a3870dd45c6a0" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", + "strsim 0.10.0", + "termcolor", + "terminal_size", + "textwrap 0.15.0", +] + +[[package]] +name = "clap_complete" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da92e6facd8d73c22745a5d3cbb59bdf8e46e3235c923e516527d8e81eec14a4" +dependencies = [ + "clap 3.1.17", +] + +[[package]] +name = "clap_derive" +version = "3.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" +dependencies = [ + "heck 0.4.0", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", +] + +[[package]] name = "cmac" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -479,7 +527,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "itertools 0.10.3", @@ -1255,6 +1303,12 @@ dependencies = [ ] [[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1874,6 +1928,12 @@ dependencies = [ ] [[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" + +[[package]] name = "p256" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2541,7 +2601,7 @@ dependencies = [ "anyhow", "buffered-reader", "capnp-rpc", - "clap", + "clap 2.34.0", "ctor", "dirs", "fs2", @@ -2649,7 +2709,8 @@ dependencies = [ "assert_cmd", "buffered-reader", "chrono", - "clap", + "clap 3.1.17", + "clap_complete", "fehler", "itertools 0.10.3", "predicates", @@ -2904,12 +2965,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] name = "structopt" version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap", + "clap 2.34.0", "lazy_static", "structopt-derive", ] @@ -2920,7 +2987,7 @@ version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck", + "heck 0.3.3", "proc-macro-error", "proc-macro2", "quote", @@ -3117,6 +3184,16 @@ dependencies = [ ] [[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] name = "termtree" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3128,7 +3205,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "term_size", "unicode-width", ] @@ -3144,6 +3220,15 @@ dependencies = [ ] [[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +dependencies = [ + "terminal_size", +] + +[[package]] name = "thiserror" version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/sq/Cargo.toml b/sq/Cargo.toml index 2007616d..47f121ea 100644 --- a/sq/Cargo.toml +++ b/sq/Cargo.toml @@ -32,7 +32,7 @@ sequoia-autocrypt = { path = "../autocrypt", version = "0.24", default-features sequoia-net = { path = "../net", version = "0.24", default-features = false } anyhow = "1.0.18" chrono = "0.4.10" -clap = { version = "2.33", features = ["wrap_help"] } +clap = { version = "3", features = ["derive", "wrap_help"] } itertools = "0.10" tempfile = "3.1" term_size = "0.3" @@ -40,7 +40,8 @@ tokio = { version = "1.13.1" } rpassword = "5.0" [build-dependencies] -clap = "2.33" +clap = "3" +clap_complete = "3" sequoia-openpgp = { path = "../openpgp", version = "1.0.0", default-features = false } subplot-build = "0.4.0" diff --git a/sq/build.rs b/sq/build.rs index 71399d46..efc13f8d 100644 --- a/sq/build.rs +++ b/sq/build.rs @@ -2,7 +2,7 @@ use std::env; use std::fs; use std::io::{self, Write}; use std::path::Path; -use clap::Shell; +use clap_complete::Shell; mod sq_cli { include!("src/sq_cli.rs"); @@ -18,7 +18,7 @@ fn main() { .expect("failed to generate code with Subplot"); let mut sq = sq_cli::configure( - clap::App::new("sq").set_term_width(80), + clap::Command::new("sq").term_width(80), cfg!(feature = "autocrypt"), ); let mut main = fs::File::create("src/sq-usage.rs").unwrap(); @@ -38,14 +38,15 @@ fn main() { }; fs::create_dir_all(&outdir).unwrap(); let mut sq = sq_cli::build(); + for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::PowerShell, Shell::Elvish] { - sq.gen_completions("sq", *shell, &outdir); - } + clap_complete::generate_to(*shell, &mut sq, "sq", &outdir).unwrap(); + }; } fn dump_help(sink: &mut dyn io::Write, - sq: &mut clap::App, + sq: &mut clap::Command, cmd: Vec<String>, heading: &str) -> io::Result<()> @@ -67,7 +68,7 @@ fn dump_help(sink: &mut dyn io::Write, .chain(std::iter::once("--help")) .collect::<Vec<_>>(); - let help = sq.get_matches_from_safe_borrow(&args) + let help = sq.try_get_matches_from_mut(&args) .unwrap_err().to_string(); writeln!(sink, "//! ```text")?; diff --git a/sq/src/commands/autocrypt.rs b/sq/src/commands/autocrypt.rs index ac852958..8ca018bf 100644 --- a/sq/src/commands/autocrypt.rs +++ b/sq/src/commands/autocrypt.rs @@ -15,7 +15,7 @@ use crate::{ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { match m.subcommand() { - ("decode", Some(m)) => { + Some(("decode", m)) => { let input = open_or_stdin(m.value_of("input"))?; let mut output = config.create_or_stdout_pgp(m.value_of("output"), @@ -29,7 +29,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { } output.finalize()?; }, - ("encode-sender", Some(m)) => { + Some(("encode-sender", m)) => { let input = open_or_stdin(m.value_of("input"))?; let mut output = config.create_or_stdout_safe(m.value_of("output"))?; diff --git a/sq/src/commands/key.rs b/sq/src/commands/key.rs index aa03f2e1..99e849d9 100644 --- a/sq/src/commands/key.rs +++ b/sq/src/commands/key.rs @@ -26,11 +26,11 @@ use crate::decrypt_key; pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { match m.subcommand() { - ("generate", Some(m)) => generate(config, m)?, - ("password", Some(m)) => password(config, m)?, - ("extract-cert", Some(m)) => extract_cert(config, m)?, - ("adopt", Some(m)) => adopt(config, m)?, - ("attest-certifications", Some(m)) => + Some(("generate", m)) => generate(config, m)?, + Some(("password", m)) => password(config, m)?, + Some(("extract-cert", m)) => extract_cert(config, m)?, + Some(("adopt", m)) => adopt(config, m)?, + Some(("attest-certifications", m)) => attest_certifications(config, m)?, _ => unreachable!(), } diff --git a/sq/src/commands/keyring.rs b/sq/src/commands/keyring.rs index 0fc2f51a..994c5fab 100644 --- a/sq/src/commands/keyring.rs +++ b/sq/src/commands/keyring.rs @@ -33,7 +33,7 @@ use crate::{ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { match m.subcommand() { - ("filter", Some(m)) => { + Some(("filter", m)) => { let any_uid_predicates = m.is_present("userid") || m.is_present("name") @@ -151,7 +151,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { to_certificate)?; output.finalize() }, - ("join", Some(m)) => { + Some(("join", m)) => { // XXX: Armor type selection is a bit problematic. If any // of the certificates contain a secret key, it would be // better to use Kind::SecretKey here. However, this @@ -164,7 +164,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { filter(m.values_of("input"), &mut output, Some, false)?; output.finalize() }, - ("merge", Some(m)) => { + Some(("merge", m)) => { let mut output = config.create_or_stdout_pgp(m.value_of("output"), m.is_present("binary"), @@ -172,11 +172,11 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { merge(m.values_of("input"), &mut output)?; output.finalize() }, - ("list", Some(m)) => { + Some(("list", m)) => { let mut input = open_or_stdin(m.value_of("input"))?; list(config, &mut input, m.is_present("all-userids")) }, - ("split", Some(m)) => { + Some(("split", m)) => { let mut input = open_or_stdin(m.value_of("input"))?; let prefix = // The prefix is either specified explicitly... diff --git a/sq/src/commands/net.rs b/sq/src/commands/net.rs index 44046ee8..dbd33227 100644 --- a/sq/src/commands/net.rs +++ b/sq/src/commands/net.rs @@ -53,7 +53,7 @@ pub fn dispatch_keyserver(config: Config, m: &clap::ArgMatches) -> Result<()> { .build()?; match m.subcommand() { - ("get", Some(m)) => { + Some(("get", m)) => { let query = m.value_of("query").unwrap(); let handle = query.parse::<KeyHandle>(); @@ -83,7 +83,7 @@ pub fn dispatch_keyserver(config: Config, m: &clap::ArgMatches) -> Result<()> { or an email address: {:?}", query)); } }, - ("send", Some(m)) => { + Some(("send", m)) => { let mut input = open_or_stdin(m.value_of("input"))?; let cert = Cert::from_reader(&mut input). context("Malformed key")?; @@ -106,7 +106,7 @@ pub fn dispatch_wkd(config: Config, m: &clap::ArgMatches) -> Result<()> { .build()?; match m.subcommand() { - ("url", Some(m)) => { + Some(("url", m)) => { let email_address = m.value_of("input").unwrap(); let wkd_url = wkd::Url::from(email_address)?; // XXX: Add other subcomand to specify whether it should be @@ -114,7 +114,7 @@ pub fn dispatch_wkd(config: Config, m: &clap::ArgMatches) -> Result<()> { let url = wkd_url.to_url(None)?; println!("{}", url); }, - ("get", Some(m)) => { + Some(("get", m)) => { // Check that the policy allows https. network_policy.assert(net::Policy::Encrypted)?; @@ -137,7 +137,7 @@ pub fn dispatch_wkd(config: Config, m: &clap::ArgMatches) -> Result<()> { serialize_keyring(&mut output, &certs, m.is_present("binary"))?; }, - ("generate", Some(m)) => { + Some(("generate", m)) => { let domain = m.value_of("domain").unwrap(); let skip = m.is_present("skip"); let f = open_or_stdin(m.value_of("input"))?; diff --git a/sq/src/commands/revoke.rs b/sq/src/commands/revoke.rs index b863f245..3e020ea0 100644 --- a/sq/src/commands/revoke.rs +++ b/sq/src/commands/revoke.rs @@ -47,8 +47,8 @@ impl Subcommand { pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { let (subcommand, m) = match m.subcommand() { - ("certificate", Some(m)) => (Subcommand::Certificate, m), - ("subkey", Some(m)) => { + Some(("certificate", m)) => (Subcommand::Certificate, m), + Some(("subkey", m)) => { let subkey = m.value_of("subkey").expect("required"); let kh: KeyHandle = subkey .parse() @@ -58,7 +58,7 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { (Subcommand::Subkey(kh), m) } - ("userid", Some(m)) => { + Some(("userid", m)) => { let userid = m.value_of("userid").expect("required"); (Subcommand::UserID(userid.into()), m) diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index c588c213..66ba9d38 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -18,42 +18,56 @@ //! to refer to OpenPGP keys that do contain secrets. //! //! USAGE: -//! sq [FLAGS] [OPTIONS] <SUBCOMMAND> +//! sq [OPTIONS] <SUBCOMMAND> //! -//! FLAGS: +//! OPTIONS: //! -f, --force //! Overwrites existing files //! //! -h, --help -//! Prints help information -//! -//! -V, --version -//! Prints version information +//! Print help information //! -//! -//! OPTIONS: -//! --known-notation <NOTATION>... +//! --known-notation <NOTATION> //! Adds NOTATION to the list of known notations. This is used when //! validating signatures. Signatures that have unknown notations with //! the critical bit set are considered invalid. //! +//! -V, --version +//! Print version information +//! //! SUBCOMMANDS: -//! encrypt Encrypts a message -//! decrypt Decrypts a message -//! sign Signs messages or data files -//! verify Verifies signed messages or detached signatures -//! key Manages keys -//! keyring Manages collections of keys or certs -//! certify Certifies a User ID for a Certificate -//! autocrypt Communicates certificates using Autocrypt -//! keyserver Interacts with keyservers -//! wkd Interacts with Web Key Directories -//! armor Converts binary to ASCII -//! dearmor Converts ASCII to binary -//! inspect Inspects data, like file(1) -//! packet Low-level packet manipulation -//! revoke Generates revocation certificates -//! help Prints this message or the help of the given subcommand(s) +//! encrypt +//! Encrypts a message +//! decrypt +//! Decrypts a message +//! sign +//! Signs messages or data files +//! verify +//! Verifies signed messages or detached signatures +//! key +//! Manages keys +//! keyring +//! Manages collections of keys or certs +//! certify +//! Certifies a User ID for a Certificate +//! autocrypt +//! Communicates certificates using Autocrypt +//! keyserver +//! Interacts with keyservers +//! wkd +//! Interacts with Web Key Directories +//! armor +//! Converts binary to ASCII +//! dearmor +//! Converts ASCII to binary +//! inspect +//! Inspects data, like file(1) +//! packet +//! Low-level packet manipulation +//! revoke +//! Generates revocation certificates +//! help +//! Print this message or the help of the given subcommand(s) //! ``` //! //! ## Subcommand encrypt @@ -67,52 +81,57 @@ //! The converse operation is "sq decrypt". //! //! USAGE: -//! sq encrypt [FLAGS] [OPTIONS] [--] [FILE] +//! sq encrypt [OPTIONS] [FILE] +//! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! -//! FLAGS: +//! OPTIONS: //! -B, --binary //! Emits binary data //! -//! -h, --help -//! Prints help information +//! --compression <KIND> +//! Selects compression scheme to use +//! +//! [default: pad] +//! [possible values: none, pad, zip, zlib, bzip2] //! -//! -s, --symmetric -//! Adds a password to encrypt with. The message can be decrypted with -//! either one of the recipient's keys, or any password. -//! --use-expired-subkey -//! If a certificate has only expired encryption-capable subkeys, falls -//! back to using the one that expired last +//! -h, --help +//! Print help information //! -//! OPTIONS: -//! --compression <KIND> -//! Selects compression scheme to use [default: pad] [possible values: -//! none, pad, zip, zlib, bzip2] //! --mode <MODE> //! Selects what kind of keys are considered for encryption. Transport //! select subkeys marked as suitable for transport encryption, rest //! selects those for encrypting data at rest, and all selects all -//! encryption-capable subkeys. [default: all] [possible values: -//! transport, rest, all] +//! encryption-capable subkeys. +//! +//! [default: all] +//! [possible values: transport, rest, all] +//! //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! //! --private-key-store <KEY_STORE> //! Provides parameters for private key store //! -//! --recipient-cert <CERT-RING>... +//! --recipient-cert <CERT-RING> //! Encrypts for all recipients in CERT-RING //! -//! --signer-key <KEY>... +//! -s, --symmetric +//! Adds a password to encrypt with. The message can be decrypted with +//! either one of the recipient's keys, or any password. +//! +//! --signer-key <KEY> //! Signs the message with KEY //! //! -t, --time <TIME> //! Chooses keys valid at the specified time and sets the signature's //! creation time //! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! +//! --use-expired-subkey +//! If a certificate has only expired encryption-capable subkeys, falls +//! back to using the one that expired last //! //! EXAMPLES: //! @@ -150,9 +169,13 @@ //! The converse operation is "sq encrypt". //! //! USAGE: -//! sq decrypt [FLAGS] [OPTIONS] [--] [FILE] +//! sq decrypt [OPTIONS] [FILE] +//! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! -//! FLAGS: +//! OPTIONS: //! --dump //! Prints a packet dump to stderr //! @@ -160,34 +183,27 @@ //! Prints the session key to stderr //! //! -h, --help -//! Prints help information -//! -//! -x, --hex -//! Prints a hexdump (implies --dump) +//! Print help information //! +//! -n, --signatures <N> +//! Sets the threshold of valid signatures to N. The message will only +//! be considered verified if this threshold is reached. [default: 1 if +//! at least one signer cert file is given, 0 otherwise] //! -//! OPTIONS: //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! //! --private-key-store <KEY_STORE> //! Provides parameters for private key store //! -//! --recipient-key <KEY>... +//! --recipient-key <KEY> //! Decrypts with KEY //! -//! --signer-cert <CERT>... +//! --signer-cert <CERT> //! Verifies signatures with CERT //! -//! -n, --signatures <N> -//! Sets the threshold of valid signatures to N. The message will only -//! be considered verified if this threshold is reached. [default: 1 if -//! at least one signer cert file is given, 0 otherwise] -//! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! +//! -x, --hex +//! Prints a hexdump (implies --dump) //! //! EXAMPLES: //! @@ -212,9 +228,13 @@ //! The converse operation is "sq verify". //! //! USAGE: -//! sq sign [FLAGS] [OPTIONS] [--] [FILE] +//! sq sign [OPTIONS] [--] [FILE] //! -//! FLAGS: +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted +//! +//! OPTIONS: //! -a, --append //! Appends a signature to existing signature //! @@ -228,16 +248,14 @@ //! Creates a detached signature //! //! -h, --help -//! Prints help information -//! -//! -n, --notarize -//! Signs a message and all existing signatures +//! Print help information //! -//! -//! OPTIONS: //! --merge <SIGNED-MESSAGE> //! Merges signatures from the input and SIGNED-MESSAGE //! +//! -n, --notarize +//! Signs a message and all existing signatures +//! //! --notation <NAME> <VALUE> //! Adds a notation to the certification. A user-defined notation's //! name must be of the form "name@a.domain.you.control.org". If the @@ -245,24 +263,20 @@ //! being critical. If a consumer of a signature doesn't understand a //! critical notation, then it will ignore the signature. The notation //! is marked as being human readable. +//! //! -o, --output <FILE> //! Writes to FILE or stdout if omitted //! //! --private-key-store <KEY_STORE> //! Provides parameters for private key store //! -//! --signer-key <KEY>... +//! --signer-key <KEY> //! Signs using KEY //! //! -t, --time <TIME> //! Chooses keys valid at the specified time and sets the signature's //! creation time //! -//! ARGS: -//! <FILE> -//! Reads from FILE or stdin if omitted -//! -//! //! EXAMPLES: //! //! # Create a signed message @@ -294,32 +308,30 @@ //! The converse operation is "sq sign". //! //! USAGE: -//! sq verify [OPTIONS] [--] [FILE] -//! -//! FLAGS: -//! -h, --help -//! Prints help information +//! sq verify [OPTIONS] [FILE] //! +//! ARGS: +//! <FILE> +//! Reads from FILE or stdin if omitted //! //! OPTIONS: //! --detached <SIG> //! Verifies a detached signature //! -//! -o, --output <FILE> -//! Writes to FILE or stdout if omitted -//! -//! --signer-cert <CERT>... -//! Verifies signatures with CERT +//! -h, --help +//! Print help information //! //! -n, --signatures <N> //! Sets the threshold of valid signatures to N. If this threshold is -//! not reached, the message will not be considered verified. [default: < |