diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index eb7523a3..314b5697 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -20,10 +20,8 @@ use std::future::Future; use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; -use structopt::clap; -use structopt::clap::ErrorKind; use swap::bitcoin::TxLock; -use swap::cli::command::{parse_args_and_apply_defaults, Arguments, Command}; +use swap::cli::command::{parse_args_and_apply_defaults, Arguments, Command, ParseResult}; use swap::database::Database; use swap::env::Config; use swap::network::quote::BidQuote; @@ -47,21 +45,11 @@ async fn main() -> Result<()> { debug, json, cmd, - } = match parse_args_and_apply_defaults(env::args_os()) { - Ok(args) => args, - Err(e) => { - if let Some(clap_err) = e.downcast_ref::() { - match clap_err.kind { - ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => { - println!("{}", clap_err.message); - std::process::exit(0); - } - _ => { - bail!(e); - } - } - } - bail!(e); + } = match parse_args_and_apply_defaults(env::args_os())? { + ParseResult::Arguments(args) => args, + ParseResult::PrintAndExitZero { message } => { + println!("{}", message); + std::process::exit(0); } }; diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 3af1c944..4b3f672b 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -7,7 +7,7 @@ use libp2p::PeerId; use std::ffi::OsString; use std::path::PathBuf; use std::str::FromStr; -use structopt::StructOpt; +use structopt::{clap, StructOpt}; use url::Url; use uuid::Uuid; @@ -34,13 +34,37 @@ pub struct Arguments { pub cmd: Command, } -pub fn parse_args_and_apply_defaults(raw_args: I) -> Result +/// Represents the result of parsing the command-line parameters. +#[derive(Debug, PartialEq)] +pub enum ParseResult { + /// The arguments we were invoked in. + Arguments(Arguments), + /// A flag or command was given that does not need further processing other + /// than printing the provided message. + /// + /// The caller should exit the program with exit code 0. + PrintAndExitZero { message: String }, +} + +pub fn parse_args_and_apply_defaults(raw_args: I) -> Result where I: IntoIterator, T: Into + Clone, { - let matches = RawArguments::clap().get_matches_from_safe(raw_args)?; - let args = RawArguments::from_clap(&matches); + let args = match RawArguments::clap().get_matches_from_safe(raw_args) { + Ok(matches) => RawArguments::from_clap(&matches), + Err(clap::Error { + message, + kind: clap::ErrorKind::HelpDisplayed, + .. + }) + | Err(clap::Error { + message, + kind: clap::ErrorKind::VersionDisplayed, + .. + }) => return Ok(ParseResult::PrintAndExitZero { message }), + Err(e) => anyhow::bail!(e), + }; let debug = args.debug; let json = args.json; @@ -176,7 +200,7 @@ where }, }; - Ok(arguments) + Ok(ParseResult::Arguments(arguments)) } #[derive(Debug, PartialEq)] @@ -490,8 +514,9 @@ mod tests { PEER_ID, ]; - let expected_args = Arguments::buy_xmr_mainnet_defaults(); + let expected_args = ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults()); let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + assert_eq!(expected_args, args); } @@ -510,7 +535,11 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::buy_xmr_testnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults()) + ); } #[test] @@ -576,7 +605,11 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::resume_mainnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::resume_mainnet_defaults()) + ); } #[test] @@ -594,7 +627,11 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::resume_testnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::resume_testnet_defaults()) + ); } #[test] @@ -602,7 +639,11 @@ mod tests { let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::cancel_mainnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::cancel_mainnet_defaults()) + ); } #[test] @@ -610,7 +651,11 @@ mod tests { let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::cancel_testnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::cancel_testnet_defaults()) + ); } #[test] @@ -618,7 +663,11 @@ mod tests { let raw_ars = vec![BINARY_NAME, "refund", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::refund_mainnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::refund_mainnet_defaults()) + ); } #[test] @@ -626,7 +675,11 @@ mod tests { let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::refund_testnet_defaults()); + + assert_eq!( + args, + ParseResult::Arguments(Arguments::refund_testnet_defaults()) + ); } #[test] @@ -647,10 +700,13 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + assert_eq!( args, - Arguments::buy_xmr_mainnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ParseResult::Arguments( + Arguments::buy_xmr_mainnet_defaults() + .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ) ); let raw_ars = vec![ @@ -668,10 +724,13 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + assert_eq!( args, - Arguments::buy_xmr_testnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ParseResult::Arguments( + Arguments::buy_xmr_testnet_defaults() + .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ) ); let raw_ars = vec![ @@ -688,10 +747,13 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + assert_eq!( args, - Arguments::resume_mainnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ParseResult::Arguments( + Arguments::resume_mainnet_defaults() + .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ) ); let raw_ars = vec![ @@ -709,10 +771,13 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + assert_eq!( args, - Arguments::resume_testnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ParseResult::Arguments( + Arguments::resume_testnet_defaults() + .with_data_dir(PathBuf::from_str(data_dir).unwrap()) + ) ); } @@ -731,7 +796,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::buy_xmr_mainnet_defaults().with_debug()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().with_debug()) + ); let raw_ars = vec![ BINARY_NAME, @@ -747,7 +815,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::buy_xmr_testnet_defaults().with_debug()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_debug()) + ); let raw_ars = vec![ BINARY_NAME, @@ -762,7 +833,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::resume_mainnet_defaults().with_debug()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::resume_mainnet_defaults().with_debug()) + ); let raw_ars = vec![ BINARY_NAME, @@ -778,7 +852,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::resume_testnet_defaults().with_debug()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::resume_testnet_defaults().with_debug()) + ); } #[test] @@ -796,7 +873,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::buy_xmr_mainnet_defaults().with_json()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().with_json()) + ); let raw_ars = vec![ BINARY_NAME, @@ -812,7 +892,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::buy_xmr_testnet_defaults().with_json()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_json()) + ); let raw_ars = vec![ BINARY_NAME, @@ -827,7 +910,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::resume_mainnet_defaults().with_json()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::resume_mainnet_defaults().with_json()) + ); let raw_ars = vec![ BINARY_NAME, @@ -843,7 +929,10 @@ mod tests { ]; let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!(args, Arguments::resume_testnet_defaults().with_json()); + assert_eq!( + args, + ParseResult::Arguments(Arguments::resume_testnet_defaults().with_json()) + ); } impl Arguments {