diff options
author | Nora Widdecke <nora@sequoia-pgp.org> | 2022-06-02 18:12:06 +0200 |
---|---|---|
committer | Nora Widdecke <nora@sequoia-pgp.org> | 2022-06-08 14:49:43 +0200 |
commit | 3bf3801a5652248651177d50c9ce058de8984e75 (patch) | |
tree | 0b307e6d80c624db96d5cbe2acb5421c3c9aa902 | |
parent | 602fb1411b8715d927291e4ba9f7f3bdf3be2bef (diff) |
sq: Adapt autocrypt command to clap3's derive.
- This is part of the effort of moving to clap3's derive API and
profit from the added type safety.
-rw-r--r-- | sq/src/commands/autocrypt.rs | 35 | ||||
-rw-r--r-- | sq/src/sq.rs | 7 | ||||
-rw-r--r-- | sq/src/sq_cli.rs | 147 |
3 files changed, 106 insertions, 83 deletions
diff --git a/sq/src/commands/autocrypt.rs b/sq/src/commands/autocrypt.rs index 8ca018bf..748e71ea 100644 --- a/sq/src/commands/autocrypt.rs +++ b/sq/src/commands/autocrypt.rs @@ -11,16 +11,21 @@ use sequoia_autocrypt as autocrypt; use crate::{ Config, open_or_stdin, + sq_cli, }; -pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { - match m.subcommand() { - Some(("decode", m)) => { - let input = open_or_stdin(m.value_of("input"))?; - let mut output = - config.create_or_stdout_pgp(m.value_of("output"), - m.is_present("binary"), - armor::Kind::PublicKey)?; +use sq_cli::autocrypt::{AutocryptSubcommands, AutocryptCommand}; + +pub fn dispatch(config: Config, c: &AutocryptCommand) -> Result<()> { + + match &c.subcommand { + AutocryptSubcommands::Decode(command) => { + let input = open_or_stdin(command.io.input.as_deref())?; + let mut output = config.create_or_stdout_pgp( + command.io.output.as_deref(), + command.binary, + armor::Kind::PublicKey, + )?; let ac = autocrypt::AutocryptHeaders::from_reader(input)?; for h in &ac.headers { if let Some(ref cert) = h.key { @@ -28,13 +33,13 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { } } output.finalize()?; - }, - Some(("encode-sender", m)) => { - let input = open_or_stdin(m.value_of("input"))?; + } + AutocryptSubcommands::EncodeSender(command) => { + let input = open_or_stdin(command.io.input.as_deref())?; let mut output = - config.create_or_stdout_safe(m.value_of("output"))?; + config.create_or_stdout_safe(command.io.output.as_deref())?; let cert = Cert::from_reader(input)?; - let addr = m.value_of("address").map(|a| a.to_string()) + let addr = command.address.clone() .or_else(|| { cert.with_policy(&config.policy, None) .and_then(|vcert| vcert.primary_userid()).ok() @@ -46,12 +51,12 @@ pub fn dispatch(config: Config, m: &clap::ArgMatches) -> Result<()> { &addr.ok_or_else(|| anyhow::anyhow!( "No well-formed primary userid found, use \ --address to specify one"))?, - m.value_of("prefer-encrypt").expect("has default"))?; + Some(command.prefer_encrypt.to_string().as_str()))?; write!(&mut output, "Autocrypt: ")?; ac.serialize(&mut output)?; }, - _ => unreachable!(), } Ok(()) } + diff --git a/sq/src/sq.rs b/sq/src/sq.rs index 09565961..87a476f6 100644 --- a/sq/src/sq.rs +++ b/sq/src/sq.rs @@ -641,8 +641,11 @@ fn main() -> Result<()> { io::copy(&mut filter, &mut output)?; }, #[cfg(feature = "autocrypt")] - Some(("autocrypt", m)) => commands::autocrypt::dispatch(config, m)?, - + Some(("autocrypt", m)) => { + use clap::FromArgMatches; + let command = sq_cli::autocrypt::AutocryptCommand::from_arg_matches(m)?; + commands::autocrypt::dispatch(config, &command)?; + }, Some(("inspect", m)) => { // sq inspect does not have --output, but commands::inspect does. // Work around this mismatch by always creating a stdout output. diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs index 2caf4bec..a536cf4f 100644 --- a/sq/src/sq_cli.rs +++ b/sq/src/sq_cli.rs @@ -1618,7 +1618,7 @@ as being human readable.")) app } else { // With Autocrypt support. - app.subcommand(AutocryptCommand::command()) + app.subcommand(autocrypt::AutocryptCommand::command()) } .subcommand(ArmorCommand::command()) .subcommand(DearmorCommand::command()) @@ -1936,11 +1936,16 @@ pub struct SignCommand { pub notation: Option<Vec<String>>, } -#[derive(Parser, Debug)] -#[clap(name = "autocrypt", display_order(400))] -#[clap( - about = "Communicates certificates using Autocrypt", - long_about = +#[cfg(feature = "autocrypt")] +pub mod autocrypt { + use super::*; + + #[derive(Parser, Debug)] + #[clap( + name = "autocrypt", + display_order(400), + about = "Communicates certificates using Autocrypt", + long_about = "Communicates certificates using Autocrypt Autocrypt is a standard for mail user agents to provide convenient @@ -1950,24 +1955,25 @@ communicate certificates between clients. See https://autocrypt.org/ ", - subcommand_required = true, - arg_required_else_help = true, -)] -pub struct AutocryptCommand { - #[clap(subcommand)] - subcommand: AutocryptSubCommands, -} + subcommand_required = true, + arg_required_else_help = true, + )] + pub struct AutocryptCommand { + #[clap(subcommand)] + pub subcommand: AutocryptSubcommands, + } -#[derive(Debug, Subcommand)] -pub enum AutocryptSubCommands { - Decode(AutocyptDecodeCommand), + #[derive(Debug, Subcommand)] + pub enum AutocryptSubcommands { + Decode(AutocryptDecodeCommand), - EncodeSender(AutocyptEncodeSenderCommand), -} -#[derive(Debug, Args)] -#[clap( - about = "Reads Autocrypt-encoded certificates", - long_about = + EncodeSender(AutocryptEncodeSenderCommand), + } + + #[derive(Debug, Args)] + #[clap( + about = "Reads Autocrypt-encoded certificates", + long_about = "Reads Autocrypt-encoded certificates Given an autocrypt header (or an key-gossip header), this command @@ -1975,30 +1981,30 @@ extracts the certificate encoded within it. The converse operation is \"sq autocrypt encode-sender\". ", - after_help = + after_help = "EXAMPLES: # Extract all certificates from a mail $ sq autocrypt decode autocrypt.eml ", -)] -pub struct AutocyptDecodeCommand { - #[clap(flatten)] - pub io: IoArgs, - #[clap( - short = 'B', - long, - help = "Emits binary data", )] - pub binary: bool, -} + pub struct AutocryptDecodeCommand { + #[clap(flatten)] + pub io: IoArgs, + #[clap( + short = 'B', + long, + help = "Emits binary data", + )] + pub binary: bool, + } -//#[derive(Subcommand)] -#[derive(Debug, Args)] -#[clap( - name = "encode-sender", - about = "Encodes a certificate into an Autocrypt header", - long_about = + //#[derive(Subcommand)] + #[derive(Debug, Args)] + #[clap( + name = "encode-sender", + about = "Encodes a certificate into an Autocrypt header", + long_about = "Encodes a certificate into an Autocrypt header A certificate can be encoded and included in a header of an email @@ -2009,7 +2015,7 @@ information). The converse operation is \"sq autocrypt decode\". ", - after_help = + after_help = "EXAMPLES: # Encodes a certificate @@ -2021,33 +2027,42 @@ $ sq autocrypt encode-sender --email juliet@example.org juliet.pgp # Encodes a certificate while indicating the willingness to encrypt $ sq autocrypt encode-sender --prefer-encrypt mutual juliet.pgp ", -)] -pub struct AutocyptEncodeSenderCommand { - #[clap(flatten)] - pub io: IoArgs, - // TODO the help message looks like "primary userid" might be the default - // email. clarify - #[clap( - long = "email", - value_name = "ADDRESS", - help = "Sets the address [default: primary userid]", )] - pub address: Option<String>, - #[clap( - long = "prefer-encrypt", - value_name = "PREFER-ENCRYPT", - default_value_t = PreferEncryptArgs::NoPreference, - help = "Sets the prefer-encrypt attribute", - arg_enum, - )] - pub prefer_encrypt: PreferEncryptArgs, + pub struct AutocryptEncodeSenderCommand { + #[clap(flatten)] + pub io: IoArgs, + // TODO the help message looks like "primary userid" might be the default + // email. clarify + #[clap( + long = "email", + value_name = "ADDRESS", + help = "Sets the address [default: primary userid]", + )] + pub address: Option<String>, + #[clap( + long = "prefer-encrypt", + value_name = "PREFER-ENCRYPT", + default_value_t = PreferEncryptArgs::NoPreference, + help = "Sets the prefer-encrypt attribute", + arg_enum, + )] + pub prefer_encrypt: PreferEncryptArgs, -} + } -#[derive(ArgEnum)] -#[derive(Debug, Clone)] -pub enum PreferEncryptArgs { - #[clap(name = "nopreference")] - NoPreference, - Mutual + #[derive(ArgEnum, Debug, Clone)] + pub enum PreferEncryptArgs { + #[clap(name = "nopreference")] + NoPreference, + Mutual + } + + impl std::fmt::Display for PreferEncryptArgs { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + PreferEncryptArgs::Mutual => write!(f, "mutual"), + PreferEncryptArgs::NoPreference => write!(f, "nopreference"), + } + } + } } |