summaryrefslogtreecommitdiffstats
path: root/tool
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-03-09 11:42:45 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-03-09 18:09:50 +0100
commit391a4b92c977cd64dfd131f3e29b0bc8d756d064 (patch)
treeb5b96ff935853cef9ee22e01890c248a791e724e /tool
parent58d662c6d37dd1b0dccd4d0ce30290b8ede408e9 (diff)
Switch from failure to anyhow.
- Use the anyhow crate instead of failure to implement the dynamic side of our error handling. anyhow::Error derefs to dyn std::error::Error, allowing better interoperability with other stdlib-based error handling libraries. - Fixes #444.
Diffstat (limited to 'tool')
-rw-r--r--tool/Cargo.toml2
-rw-r--r--tool/src/commands/decrypt.rs13
-rw-r--r--tool/src/commands/key.rs32
-rw-r--r--tool/src/commands/mod.rs19
-rw-r--r--tool/src/commands/sign.rs12
-rw-r--r--tool/src/sq.rs25
6 files changed, 36 insertions, 67 deletions
diff --git a/tool/Cargo.toml b/tool/Cargo.toml
index 10832d54..3139bc9a 100644
--- a/tool/Cargo.toml
+++ b/tool/Cargo.toml
@@ -27,9 +27,9 @@ sequoia-autocrypt = { path = "../autocrypt", version = "0.15" }
sequoia-core = { path = "../core", version = "0.15" }
sequoia-net = { path = "../net", version = "0.15" }
sequoia-store = { path = "../store", version = "0.15" }
+anyhow = "1"
chrono = "0.4"
clap = "2.32.0"
-failure = "0.1.2"
itertools = "0.8"
prettytable-rs = "0.8.0"
rpassword = "=4.0.3"
diff --git a/tool/src/commands/decrypt.rs b/tool/src/commands/decrypt.rs
index 65b9d579..964fd6c8 100644
--- a/tool/src/commands/decrypt.rs
+++ b/tool/src/commands/decrypt.rs
@@ -1,5 +1,5 @@
use crossterm::terminal;
-use failure::{self, ResultExt};
+use anyhow::Context as _;
use std::collections::HashMap;
use std::io;
use rpassword;
@@ -253,7 +253,7 @@ impl<'a> DecryptionHelper for Helper<'a> {
if skesks.is_empty() {
return
- Err(failure::err_msg("No key to decrypt message"));
+ Err(anyhow::anyhow!("No key to decrypt message"));
}
// Finally, try to decrypt using the SKESKs.
@@ -289,14 +289,7 @@ pub fn decrypt(ctx: &Context, policy: &dyn Policy, mapping: &mut store::Mapping,
let mut decryptor = Decryptor::from_reader(policy, input, helper, None)
.context("Decryption failed")?;
- io::copy(&mut decryptor, output)
- .map_err(|e| if e.get_ref().is_some() {
- // Wrapped failure::Error. Recover it.
- failure::Error::from_boxed_compat(e.into_inner().unwrap())
- } else {
- // Plain io::Error.
- e.into()
- }).context("Decryption failed")?;
+ io::copy(&mut decryptor, output).context("Decryption failed")?;
let helper = decryptor.into_helper();
if let Some(dumper) = helper.dumper.as_ref() {
diff --git a/tool/src/commands/key.rs b/tool/src/commands/key.rs
index bbde9ceb..688633a8 100644
--- a/tool/src/commands/key.rs
+++ b/tool/src/commands/key.rs
@@ -1,5 +1,4 @@
-use failure;
-use failure::Fail;
+use anyhow::Context as _;
use clap::ArgMatches;
use itertools::Itertools;
use std::time::{SystemTime, Duration};
@@ -66,7 +65,7 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
builder = builder.set_cipher_suite(CipherSuite::Cv25519);
}
Some(ref cs) => {
- return Err(format_err!("Unknown cipher suite '{}'", cs));
+ return Err(anyhow::anyhow!("Unknown cipher suite '{}'", cs));
}
None => panic!("argument has a default value"),
}
@@ -79,7 +78,7 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
(false, true) => { /* no signing subkey */ }
(true, true) => {
return Err(
- format_err!("Conflicting arguments --can-sign and --cannot-sign"));
+ anyhow::anyhow!("Conflicting arguments --can-sign and --cannot-sign"));
}
}
@@ -101,12 +100,12 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
(None, true) => { /* no encryption subkey */ }
(Some(_), true) => {
return Err(
- format_err!("Conflicting arguments --can-encrypt and \
+ anyhow::anyhow!("Conflicting arguments --can-encrypt and \
--cannot-encrypt"));
}
(Some(ref cap), false) => {
return Err(
- format_err!("Unknown encryption capability '{}'", cap));
+ anyhow::anyhow!("Unknown encryption capability '{}'", cap));
}
}
@@ -119,7 +118,7 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
if p0 == p1 {
builder = builder.set_password(Some(p0));
} else {
- return Err(failure::err_msg("Passwords do not match."));
+ return Err(anyhow::anyhow!("Passwords do not match."));
}
}
@@ -136,7 +135,7 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
("-".to_string(), rp.to_string()),
(Some("-"), None) =>
return Err(
- format_err!("Missing arguments: --rev-cert is mandatory \
+ anyhow::anyhow!("Missing arguments: --rev-cert is mandatory \
if --export is '-'.")),
(Some(ref kp), None) =>
(kp.to_string(), format!("{}.rev", kp)),
@@ -146,7 +145,7 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
(kp.to_string(), rp.to_string()),
_ =>
return Err(
- format_err!("Conflicting arguments --rev-cert and \
+ anyhow::anyhow!("Conflicting arguments --rev-cert and \
--export")),
};
@@ -178,7 +177,7 @@ pub fn generate(m: &ArgMatches, force: bool) -> Result<()> {
}
} else {
return Err(
- format_err!("Saving generated key to the store isn't implemented \
+ anyhow::anyhow!("Saving generated key to the store isn't implemented \
yet."));
}
@@ -205,19 +204,18 @@ fn parse_duration(expiry: &str) -> Result<Duration> {
let junk = expiry.collect::<String>();
if digits == "" {
- return Err(format_err!(
+ return Err(anyhow::anyhow!(
"--expiry: missing count \
(try: '2y' for 2 years)"));
}
let count = match digits.parse::<i32>() {
Ok(count) if count < 0 =>
- return Err(format_err!(
+ return Err(anyhow::anyhow!(
"--expiry: Expiration can't be in the past")),
Ok(count) => count as u64,
Err(err) =>
- return Err(err.context(
- "--expiry: count is out of range").into()),
+ return Err(err).context("--expiry: count is out of range"),
};
let factor = match suffix {
@@ -226,19 +224,19 @@ fn parse_duration(expiry: &str) -> Result<Duration> {
Some('w') | Some('W') => 7 * SECONDS_IN_DAY,
Some('d') | Some('D') => SECONDS_IN_DAY,
None =>
- return Err(format_err!(
+ return Err(anyhow::anyhow!(
"--expiry: missing suffix \
(try: '{}y', '{}m', '{}w' or '{}d' instead)",
digits, digits, digits, digits)),
Some(suffix) =>
- return Err(format_err!(
+ return Err(anyhow::anyhow!(
"--expiry: invalid suffix '{}' \
(try: '{}y', '{}m', '{}w' or '{}d' instead)",
suffix, digits, digits, digits, digits)),
};
if junk != "" {
- return Err(format_err!(
+ return Err(anyhow::anyhow!(
"--expiry: contains trailing junk ('{:?}') \
(try: '{}{}')",
junk, count, factor));
diff --git a/tool/src/commands/mod.rs b/tool/src/commands/mod.rs
index a925d362..8c2fd516 100644
--- a/tool/src/commands/mod.rs
+++ b/tool/src/commands/mod.rs
@@ -1,4 +1,4 @@
-use failure::{self, ResultExt};
+use anyhow::Context as _;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet};
use std::fs::File;
@@ -78,7 +78,7 @@ fn get_signing_keys(certs: &[openpgp::Cert], p: &dyn Policy,
}
}
- return Err(failure::err_msg(
+ return Err(anyhow::anyhow!(
format!("Found no suitable signing key on {}", tsk)));
}
@@ -108,7 +108,7 @@ pub fn encrypt(policy: &dyn Policy,
}
if certs.len() + passwords.len() == 0 {
- return Err(failure::format_err!(
+ return Err(anyhow::anyhow!(
"Neither recipient nor password given"));
}
@@ -128,7 +128,7 @@ pub fn encrypt(policy: &dyn Policy,
count += 1;
}
if count == 0 {
- return Err(failure::format_err!(
+ return Err(anyhow::anyhow!(
"Key {} has no suitable encryption key", cert));
}
}
@@ -394,7 +394,7 @@ impl<'a> VerificationHelper for VHelper<'a> {
Ok(())
} else {
self.print_status();
- Err(failure::err_msg("Verification failed"))
+ Err(anyhow::anyhow!("Verification failed"))
}
}
}
@@ -413,14 +413,7 @@ pub fn verify(ctx: &Context, policy: &dyn Policy,
Verifier::from_reader(policy, input, helper, None)?
};
- io::copy(&mut verifier, output)
- .map_err(|e| if e.get_ref().is_some() {
- // Wrapped failure::Error. Recover it.
- failure::Error::from_boxed_compat(e.into_inner().unwrap())
- } else {
- // Plain io::Error.
- e.into()
- })?;
+ io::copy(&mut verifier, output)?;
verifier.into_helper().print_status();
Ok(())
diff --git a/tool/src/commands/sign.rs b/tool/src/commands/sign.rs
index 89b97a10..9a8e6819 100644
--- a/tool/src/commands/sign.rs
+++ b/tool/src/commands/sign.rs
@@ -1,4 +1,4 @@
-use failure::{self, ResultExt};
+use anyhow::Context as _;
use std::fs;
use std::io;
use std::path::PathBuf;
@@ -60,7 +60,7 @@ fn sign_data(policy: &dyn Policy,
match packet {
Packet::Signature(sig) => sigs.push(sig),
p => return Err(
- failure::err_msg(
+ anyhow::anyhow!(
format!("{} in detached signature", p.tag()))
.context("Invalid detached signature").into()),
}
@@ -91,7 +91,7 @@ fn sign_data(policy: &dyn Policy,
let mut keypairs = super::get_signing_keys(&secrets, policy, time)?;
if keypairs.is_empty() {
- return Err(failure::format_err!("No signing keys found"));
+ return Err(anyhow::anyhow!("No signing keys found"));
}
// When extending a detached signature, prepend any existing
@@ -166,7 +166,7 @@ fn sign_message_(policy: &dyn Policy,
{
let mut keypairs = super::get_signing_keys(&secrets, policy, time)?;
if keypairs.is_empty() {
- return Err(failure::format_err!("No signing keys found"));
+ return Err(anyhow::anyhow!("No signing keys found"));
}
let mut sink = Message::new(output);
@@ -205,7 +205,7 @@ fn sign_message_(policy: &dyn Policy,
match pp.packet {
Packet::PKESK(_) | Packet::SKESK(_) =>
- return Err(failure::err_msg(
+ return Err(anyhow::anyhow!(
"Signing encrypted data is not implemented")),
Packet::Literal(_) =>
@@ -223,7 +223,7 @@ fn sign_message_(policy: &dyn Policy,
// If you do implement this, there is a half-disabled test
// in tests/sq-sign.rs.
Packet::CompressedData(_) if seen_signature =>
- return Err(failure::err_msg(
+ return Err(anyhow::anyhow!(
"Signing a compress-then-sign message is not implemented")),
_ => (),
diff --git a/tool/src/sq.rs b/tool/src/sq.rs
index 6b188e0e..421dadae 100644
--- a/tool/src/sq.rs
+++ b/tool/src/sq.rs
@@ -2,8 +2,6 @@
extern crate clap;
#[macro_use]
-extern crate failure;
-#[macro_use]
extern crate prettytable;
extern crate rpassword;
extern crate tempfile;
@@ -12,7 +10,7 @@ extern crate itertools;
extern crate tokio_core;
use crossterm::terminal;
-use failure::ResultExt;
+use anyhow::Context as _;
use prettytable::{Table, Cell, Row};
use std::fs::{File, OpenOptions};
use std::io::{self, Write};
@@ -65,7 +63,7 @@ fn create_or_stdout(f: Option<&str>, force: bool)
.open(f)
.context("Failed to create output file")?))
} else {
- Err(failure::err_msg(
+ Err(anyhow::anyhow!(
format!("File {:?} exists, use --force to overwrite", p)))
}
}
@@ -213,7 +211,7 @@ fn help_warning(arg: &str) {
}
}
-fn real_main() -> Result<()> {
+fn main() -> Result<()> {
let policy = &P::new();
let matches = sq_cli::build().get_matches();
@@ -392,7 +390,7 @@ fn real_main() -> Result<()> {
let ac = autocrypt::AutocryptHeader::new_sender(
policy,
&cert,
- &addr.ok_or(failure::err_msg(
+ &addr.ok_or(anyhow::anyhow!(
"No well-formed primary userid found, use \
--address to specify one"))?,
m.value_of("prefer-encrypt").expect("has default"))?;
@@ -767,7 +765,7 @@ fn parse_iso8601(s: &str, pad_date_with: chrono::NaiveTime)
return Ok(DateTime::from_utc(d.and_time(pad_date_with), Utc));
}
}
- Err(failure::format_err!("Malformed ISO8601 timestamp: {}", s))
+ Err(anyhow::anyhow!("Malformed ISO8601 timestamp: {}", s))
}
#[test]
@@ -795,16 +793,3 @@ fn test_parse_iso8601() {
parse_iso8601("2017031", z).unwrap();
// parse_iso8601("2017", z).unwrap(); // ditto
}
-
-fn main() {
- if let Err(e) = real_main() {
- let mut cause = e.as_fail();
- eprint!("{}", cause);
- while let Some(c) = cause.cause() {
- eprint!(":\n {}", c);
- cause = c;
- }
- eprintln!();
- exit(2);
- }
-}