summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNora Widdecke <nora@sequoia-pgp.org>2022-06-02 18:12:06 +0200
committerNora Widdecke <nora@sequoia-pgp.org>2022-06-08 14:49:43 +0200
commit3bf3801a5652248651177d50c9ce058de8984e75 (patch)
tree0b307e6d80c624db96d5cbe2acb5421c3c9aa902
parent602fb1411b8715d927291e4ba9f7f3bdf3be2bef (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.rs35
-rw-r--r--sq/src/sq.rs7
-rw-r--r--sq/src/sq_cli.rs147
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"),
+ }
+ }
+ }
}