summaryrefslogtreecommitdiffhomepage
path: root/mullvad-cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'mullvad-cli/src')
-rw-r--r--mullvad-cli/src/cmds/account.rs40
-rw-r--r--mullvad-cli/src/cmds/auto_connect.rs18
-rw-r--r--mullvad-cli/src/cmds/beta_program.rs19
-rw-r--r--mullvad-cli/src/cmds/block_when_disconnected.rs15
-rw-r--r--mullvad-cli/src/cmds/bridge.rs132
-rw-r--r--mullvad-cli/src/cmds/connect.rs10
-rw-r--r--mullvad-cli/src/cmds/disconnect.rs10
-rw-r--r--mullvad-cli/src/cmds/dns.rs53
-rw-r--r--mullvad-cli/src/cmds/lan.rs24
-rw-r--r--mullvad-cli/src/cmds/reconnect.rs10
-rw-r--r--mullvad-cli/src/cmds/relay.rs147
-rw-r--r--mullvad-cli/src/cmds/reset.rs6
-rw-r--r--mullvad-cli/src/cmds/split_tunnel/linux.rs39
-rw-r--r--mullvad-cli/src/cmds/split_tunnel/windows.rs51
-rw-r--r--mullvad-cli/src/cmds/status.rs16
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs146
-rw-r--r--mullvad-cli/src/cmds/version.rs6
-rw-r--r--mullvad-cli/src/location.rs32
-rw-r--r--mullvad-cli/src/main.rs43
19 files changed, 386 insertions, 431 deletions
diff --git a/mullvad-cli/src/cmds/account.rs b/mullvad-cli/src/cmds/account.rs
index af3af0debd..0bbbc28024 100644
--- a/mullvad-cli/src/cmds/account.rs
+++ b/mullvad-cli/src/cmds/account.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Error, Result};
-use clap::value_t_or_exit;
use itertools::Itertools;
use mullvad_management_interface::{types::Timestamp, Code};
use mullvad_types::account::AccountToken;
@@ -13,43 +12,38 @@ impl Command for Account {
"account"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Control and display information about your Mullvad account")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
- .about("Change account")
- .arg(
- clap::Arg::with_name("token")
- .help("The Mullvad account token to configure the client with")
- .required(false),
- ),
+ clap::App::new("set").about("Change account").arg(
+ clap::Arg::new("token")
+ .help("The Mullvad account token to configure the client with")
+ .required(false),
+ ),
)
.subcommand(
- clap::SubCommand::with_name("get")
+ clap::App::new("get")
.about("Display information about the currently configured account"),
)
.subcommand(
- clap::SubCommand::with_name("unset")
- .about("Removes the account number from the settings"),
+ clap::App::new("unset").about("Removes the account number from the settings"),
)
.subcommand(
- clap::SubCommand::with_name("create")
+ clap::App::new("create")
.about("Creates a new account and sets it as the active one"),
)
.subcommand(
- clap::SubCommand::with_name("redeem")
- .about("Redeems a voucher")
- .arg(
- clap::Arg::with_name("voucher")
- .help("The Mullvad voucher code to be submitted")
- .required(true),
- ),
+ clap::App::new("redeem").about("Redeems a voucher").arg(
+ clap::Arg::new("voucher")
+ .help("The Mullvad voucher code to be submitted")
+ .required(true),
+ ),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
if let Some(set_matches) = matches.subcommand_matches("set") {
let mut token = match set_matches.value_of("token") {
Some(token) => token.to_string(),
@@ -74,7 +68,7 @@ impl Command for Account {
} else if let Some(_matches) = matches.subcommand_matches("create") {
self.create().await
} else if let Some(matches) = matches.subcommand_matches("redeem") {
- let voucher = value_t_or_exit!(matches.value_of("voucher"), String);
+ let voucher = matches.value_of_t_or_exit("voucher");
self.redeem_voucher(voucher).await
} else {
unreachable!("No account command given");
diff --git a/mullvad-cli/src/cmds/auto_connect.rs b/mullvad-cli/src/cmds/auto_connect.rs
index 52e62e0c70..244968dcd7 100644
--- a/mullvad-cli/src/cmds/auto_connect.rs
+++ b/mullvad-cli/src/cmds/auto_connect.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Result};
-use clap::value_t_or_exit;
pub struct AutoConnect;
@@ -9,28 +8,25 @@ impl Command for AutoConnect {
"auto-connect"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Control the daemon auto-connect setting")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
+ clap::App::new("set")
.about("Change auto-connect setting")
.arg(
- clap::Arg::with_name("policy")
+ clap::Arg::new("policy")
.required(true)
.possible_values(&["on", "off"]),
),
)
- .subcommand(
- clap::SubCommand::with_name("get")
- .about("Display the current auto-connect setting"),
- )
+ .subcommand(clap::App::new("get").about("Display the current auto-connect setting"))
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
if let Some(set_matches) = matches.subcommand_matches("set") {
- let auto_connect = value_t_or_exit!(set_matches.value_of("policy"), String);
+ let auto_connect = set_matches.value_of("policy").expect("missing policy");
self.set(auto_connect == "on").await
} else if let Some(_matches) = matches.subcommand_matches("get") {
self.get().await
diff --git a/mullvad-cli/src/cmds/beta_program.rs b/mullvad-cli/src/cmds/beta_program.rs
index 73a0ba15c7..871b28324e 100644
--- a/mullvad-cli/src/cmds/beta_program.rs
+++ b/mullvad-cli/src/cmds/beta_program.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Error, Result, PRODUCT_VERSION};
-use clap::value_t_or_exit;
pub struct BetaProgram;
@@ -9,25 +8,25 @@ impl Command for BetaProgram {
"beta-program"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Receive notifications about beta updates")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
+ clap::App::new("set")
.about("Change beta notifications setting")
.arg(
- clap::Arg::with_name("policy")
+ clap::Arg::new("policy")
.required(true)
.possible_values(&["on", "off"]),
),
)
- .subcommand(clap::SubCommand::with_name("get").about("Get beta notifications setting"))
+ .subcommand(clap::App::new("get").about("Get beta notifications setting"))
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("get", Some(_)) => {
+ Some(("get", _)) => {
let mut rpc = new_rpc_client().await?;
let settings = rpc.get_settings(()).await?.into_inner();
let enabled_str = if settings.show_beta_releases {
@@ -38,8 +37,8 @@ impl Command for BetaProgram {
println!("Beta program: {}", enabled_str);
Ok(())
}
- ("set", Some(matches)) => {
- let enable_str = value_t_or_exit!(matches.value_of("policy"), String);
+ Some(("set", matches)) => {
+ let enable_str = matches.value_of("policy").expect("missing policy");
let enable = enable_str == "on";
if !enable && PRODUCT_VERSION.contains("beta") {
diff --git a/mullvad-cli/src/cmds/block_when_disconnected.rs b/mullvad-cli/src/cmds/block_when_disconnected.rs
index 3cb1baff5a..3f7ebeef22 100644
--- a/mullvad-cli/src/cmds/block_when_disconnected.rs
+++ b/mullvad-cli/src/cmds/block_when_disconnected.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Result};
-use clap::value_t_or_exit;
pub struct BlockWhenDisconnected;
@@ -9,28 +8,28 @@ impl Command for BlockWhenDisconnected {
"always-require-vpn"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Control if the system service should block network access when disconnected from VPN")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
+ clap::App::new("set")
.about("Change the always require VPN setting")
.arg(
- clap::Arg::with_name("policy")
+ clap::Arg::new("policy")
.required(true)
.possible_values(&["on", "off"]),
),
)
.subcommand(
- clap::SubCommand::with_name("get")
+ clap::App::new("get")
.about("Display the current always require VPN setting"),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
if let Some(set_matches) = matches.subcommand_matches("set") {
- let block_when_disconnected = value_t_or_exit!(set_matches.value_of("policy"), String);
+ let block_when_disconnected = set_matches.value_of("policy").expect("missing policy");
self.set(block_when_disconnected == "on").await
} else if let Some(_matches) = matches.subcommand_matches("get") {
self.get().await
diff --git a/mullvad-cli/src/cmds/bridge.rs b/mullvad-cli/src/cmds/bridge.rs
index 3267ec3541..e1b0056a15 100644
--- a/mullvad-cli/src/cmds/bridge.rs
+++ b/mullvad-cli/src/cmds/bridge.rs
@@ -1,5 +1,4 @@
use crate::{location, new_rpc_client, Command, Error, Result};
-use clap::{value_t, values_t};
use mullvad_management_interface::types;
use mullvad_types::relay_constraints::{
@@ -7,10 +6,7 @@ use mullvad_types::relay_constraints::{
};
use talpid_types::net::openvpn::{self, SHADOWSOCKS_CIPHERS};
-use std::{
- convert::TryFrom,
- net::{IpAddr, SocketAddr},
-};
+use std::{convert::TryFrom, net::SocketAddr};
pub struct Bridge;
@@ -20,43 +16,41 @@ impl Command for Bridge {
"bridge"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Manage use of bridges")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_bridge_set_subcommand())
- .subcommand(
- clap::SubCommand::with_name("get").about("Get current bridge settings and state"),
- )
- .subcommand(clap::SubCommand::with_name("list").about("List bridge relays"))
+ .subcommand(clap::App::new("get").about("Get current bridge settings and state"))
+ .subcommand(clap::App::new("list").about("List bridge relays"))
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("set", Some(set_matches)) => Self::handle_set(set_matches).await,
- ("get", _) => Self::handle_get().await,
- ("list", _) => Self::list_bridge_relays().await,
+ Some(("set", set_matches)) => Self::handle_set(set_matches).await,
+ Some(("get", _)) => Self::handle_get().await,
+ Some(("list", _)) => Self::list_bridge_relays().await,
_ => unreachable!("unhandled command"),
}
}
}
-fn create_bridge_set_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("set")
+fn create_bridge_set_subcommand() -> clap::App<'static> {
+ clap::App::new("set")
.about("Set bridge state and settings")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_set_state_subcommand())
.subcommand(create_set_custom_settings_subcommand())
.subcommand(
- clap::SubCommand::with_name("provider")
+ clap::App::new("provider")
.about(
"Set hosting provider(s) to select bridge relays from. The 'list' \
command shows the available relays and their providers.",
)
.arg(
- clap::Arg::with_name("provider")
+ clap::Arg::new("provider")
.help("The hosting provider(s) to use, or 'any' for no preference.")
- .multiple(true)
+ .multiple_values(true)
.required(true),
),
)
@@ -66,24 +60,24 @@ fn create_bridge_set_subcommand() -> clap::App<'static, 'static> {
))
}
-fn create_set_custom_settings_subcommand() -> clap::App<'static, 'static> {
+fn create_set_custom_settings_subcommand() -> clap::App<'static> {
#[allow(unused_mut)]
- let mut local_subcommand = clap::SubCommand::with_name("local")
+ let mut local_subcommand = clap::App::new("local")
.about("Registers a local SOCKS5 proxy")
.arg(
- clap::Arg::with_name("local-port")
+ clap::Arg::new("local-port")
.help("Specifies the port the local proxy server is listening on")
.required(true)
.index(1),
)
.arg(
- clap::Arg::with_name("remote-ip")
+ clap::Arg::new("remote-ip")
.help("Specifies the IP of the proxy server peer")
.required(true)
.index(2),
)
.arg(
- clap::Arg::with_name("remote-port")
+ clap::Arg::new("remote-port")
.help("Specifies the port of the proxy server peer")
.required(true)
.index(3),
@@ -99,67 +93,67 @@ fn create_set_custom_settings_subcommand() -> clap::App<'static, 'static> {
}
#[cfg(target_os = "macos")]
{
- local_subcommand = local_subcommand.help(
+ local_subcommand = local_subcommand.about(
"Registers a local SOCKS5 proxy. The server must run as root to bypass \
firewall restrictions",
);
}
- clap::SubCommand::with_name("custom")
+ clap::App::new("custom")
.about("Configure a SOCKS5 proxy")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(local_subcommand)
.subcommand(
- clap::SubCommand::with_name("remote")
+ clap::App::new("remote")
.about("Registers a remote SOCKS5 proxy")
.arg(
- clap::Arg::with_name("remote-ip")
+ clap::Arg::new("remote-ip")
.help("Specifies the IP of the remote proxy server")
.required(true)
.index(1),
)
.arg(
- clap::Arg::with_name("remote-port")
+ clap::Arg::new("remote-port")
.help("Specifies the port the remote proxy server is listening on")
.required(true)
.index(2),
)
.arg(
- clap::Arg::with_name("username")
+ clap::Arg::new("username")
.help("Specifies the username for remote authentication")
.required(true)
.index(3),
)
.arg(
- clap::Arg::with_name("password")
+ clap::Arg::new("password")
.help("Specifies the password for remote authentication")
.required(true)
.index(4),
),
)
.subcommand(
- clap::SubCommand::with_name("shadowsocks")
+ clap::App::new("shadowsocks")
.about("Configure bundled Shadowsocks proxy")
.arg(
- clap::Arg::with_name("remote-ip")
+ clap::Arg::new("remote-ip")
.help("Specifies the IP of the remote Shadowsocks server")
.required(true)
.index(1),
)
.arg(
- clap::Arg::with_name("remote-port")
+ clap::Arg::new("remote-port")
.help("Specifies the port of the remote Shadowsocks server")
.default_value("443")
.index(2),
)
.arg(
- clap::Arg::with_name("password")
+ clap::Arg::new("password")
.help("Specifies the password on the remote Shadowsocks server")
.default_value("mullvad")
.index(3),
)
.arg(
- clap::Arg::with_name("cipher")
+ clap::Arg::new("cipher")
.help("Specifies the cipher to use")
.default_value("aes-256-gcm")
.possible_values(SHADOWSOCKS_CIPHERS)
@@ -168,31 +162,29 @@ fn create_set_custom_settings_subcommand() -> clap::App<'static, 'static> {
)
}
-fn create_set_state_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("state")
- .about("Set bridge state")
- .arg(
- clap::Arg::with_name("policy")
- .help("Specifies whether a bridge should be used")
- .required(true)
- .index(1)
- .possible_values(&["auto", "on", "off"]),
- )
+fn create_set_state_subcommand() -> clap::App<'static> {
+ clap::App::new("state").about("Set bridge state").arg(
+ clap::Arg::new("policy")
+ .help("Specifies whether a bridge should be used")
+ .required(true)
+ .index(1)
+ .possible_values(&["auto", "on", "off"]),
+ )
}
impl Bridge {
- async fn handle_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_set(matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("location", Some(location_matches)) => {
+ Some(("location", location_matches)) => {
Self::handle_set_bridge_location(location_matches).await
}
- ("provider", Some(provider_matches)) => {
+ Some(("provider", provider_matches)) => {
Self::handle_set_bridge_provider(provider_matches).await
}
- ("custom", Some(custom_matches)) => {
+ Some(("custom", custom_matches)) => {
Self::handle_bridge_set_custom_settings(custom_matches).await
}
- ("state", Some(set_matches)) => Self::handle_set_bridge_state(set_matches).await,
+ Some(("state", set_matches)) => Self::handle_set_bridge_state(set_matches).await,
_ => unreachable!("unhandled command"),
}
}
@@ -222,13 +214,12 @@ impl Bridge {
Ok(())
}
- async fn handle_set_bridge_location(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_set_bridge_location(matches: &clap::ArgMatches) -> Result<()> {
Self::update_bridge_settings(Some(location::get_constraint_from_args(matches)), None).await
}
- async fn handle_set_bridge_provider(matches: &clap::ArgMatches<'_>) -> Result<()> {
- let providers =
- values_t!(matches.values_of("provider"), String).unwrap_or_else(|e| e.exit());
+ async fn handle_set_bridge_provider(matches: &clap::ArgMatches) -> Result<()> {
+ let providers: Vec<String> = matches.values_of_t_or_exit("provider");
let providers = if providers.iter().next().map(String::as_str) == Some("any") {
vec![]
} else {
@@ -277,7 +268,7 @@ impl Bridge {
Ok(())
}
- async fn handle_set_bridge_state(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_set_bridge_state(matches: &clap::ArgMatches) -> Result<()> {
let state = match matches.value_of("policy").unwrap() {
"auto" => BridgeState::Auto,
"on" => BridgeState::On,
@@ -290,14 +281,11 @@ impl Bridge {
Ok(())
}
- async fn handle_bridge_set_custom_settings(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_bridge_set_custom_settings(matches: &clap::ArgMatches) -> Result<()> {
if let Some(args) = matches.subcommand_matches("local") {
- let local_port =
- value_t!(args.value_of("local-port"), u16).unwrap_or_else(|e| e.exit());
- let remote_ip =
- value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
- let remote_port =
- value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
+ let local_port = args.value_of_t_or_exit("local-port");
+ let remote_ip = args.value_of_t_or_exit("remote-ip");
+ let remote_port = args.value_of_t_or_exit("remote-port");
let local_proxy = openvpn::LocalProxySettings {
port: local_port,
@@ -314,10 +302,8 @@ impl Bridge {
)))
.await?;
} else if let Some(args) = matches.subcommand_matches("remote") {
- let remote_ip =
- value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
- let remote_port =
- value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
+ let remote_ip = args.value_of_t_or_exit("remote-ip");
+ let remote_port = args.value_of_t_or_exit("remote-port");
let username = args.value_of("username");
let password = args.value_of("password");
@@ -343,12 +329,10 @@ impl Bridge {
)))
.await?;
} else if let Some(args) = matches.subcommand_matches("shadowsocks") {
- let remote_ip =
- value_t!(args.value_of("remote-ip"), IpAddr).unwrap_or_else(|e| e.exit());
- let remote_port =
- value_t!(args.value_of("remote-port"), u16).unwrap_or_else(|e| e.exit());
- let password = args.value_of("password").unwrap().to_string();
- let cipher = args.value_of("cipher").unwrap().to_string();
+ let remote_ip = args.value_of_t_or_exit("remote-ip");
+ let remote_port = args.value_of_t_or_exit("remote-port");
+ let password = args.value_of_t_or_exit("password");
+ let cipher = args.value_of_t_or_exit("cipher");
let proxy = openvpn::ShadowsocksProxySettings {
peer: SocketAddr::new(remote_ip, remote_port),
diff --git a/mullvad-cli/src/cmds/connect.rs b/mullvad-cli/src/cmds/connect.rs
index c93ed8c2e2..a184e38244 100644
--- a/mullvad-cli/src/cmds/connect.rs
+++ b/mullvad-cli/src/cmds/connect.rs
@@ -10,18 +10,18 @@ impl Command for Connect {
"connect"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Command the client to start establishing a VPN tunnel")
.arg(
- clap::Arg::with_name("wait")
+ clap::Arg::new("wait")
.long("wait")
- .short("w")
+ .short('w')
.help("Wait until connected before exiting"),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let receiver_option = if matches.is_present("wait") {
diff --git a/mullvad-cli/src/cmds/disconnect.rs b/mullvad-cli/src/cmds/disconnect.rs
index 96d5843d20..9ac051ca57 100644
--- a/mullvad-cli/src/cmds/disconnect.rs
+++ b/mullvad-cli/src/cmds/disconnect.rs
@@ -10,18 +10,18 @@ impl Command for Disconnect {
"disconnect"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Command the client to disconnect the VPN tunnel")
.arg(
- clap::Arg::with_name("wait")
+ clap::Arg::new("wait")
.long("wait")
- .short("w")
+ .short('w')
.help("Wait until disconnected before exiting"),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let receiver_option = if matches.is_present("wait") {
diff --git a/mullvad-cli/src/cmds/dns.rs b/mullvad-cli/src/cmds/dns.rs
index 91562ff798..72869b6c7b 100644
--- a/mullvad-cli/src/cmds/dns.rs
+++ b/mullvad-cli/src/cmds/dns.rs
@@ -1,7 +1,7 @@
use crate::{new_rpc_client, Command, Result};
use mullvad_management_interface::types;
use mullvad_types::settings::{DnsOptions, DnsState};
-use std::convert::TryInto;
+use std::{convert::TryInto, net::IpAddr};
pub struct Dns;
@@ -11,45 +11,43 @@ impl Command for Dns {
"dns"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Configure DNS servers to use when connected")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
+ .subcommand(clap::App::new("get").about("Display the current DNS settings"))
.subcommand(
- clap::SubCommand::with_name("get").about("Display the current DNS settings"),
- )
- .subcommand(
- clap::SubCommand::with_name("set")
+ clap::App::new("set")
.about("Set DNS servers to use")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("default")
+ clap::App::new("default")
.about("Use default DNS servers")
.arg(
- clap::Arg::with_name("block ads")
+ clap::Arg::new("block ads")
.long("block-ads")
.takes_value(false)
.help("Block domain names used for ads"),
)
.arg(
- clap::Arg::with_name("block trackers")
+ clap::Arg::new("block trackers")
.long("block-trackers")
.takes_value(false)
.help("Block domain names used for tracking"),
)
.arg(
- clap::Arg::with_name("block malware")
+ clap::Arg::new("block malware")
.long("block-malware")
.takes_value(false)
.help("Block domains known to be used by malware"),
),
)
.subcommand(
- clap::SubCommand::with_name("custom")
+ clap::App::new("custom")
.about("Set a list of custom DNS servers")
.arg(
- clap::Arg::with_name("servers")
- .multiple(true)
+ clap::Arg::new("servers")
+ .multiple_occurrences(true)
.help("One or more IP addresses pointing to DNS resolvers.")
.required(true),
),
@@ -57,10 +55,10 @@ impl Command for Dns {
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("set", Some(matches)) => match matches.subcommand() {
- ("default", Some(matches)) => {
+ Some(("set", matches)) => match matches.subcommand() {
+ Some(("default", matches)) => {
self.set_default(
matches.is_present("block ads"),
matches.is_present("block trackers"),
@@ -68,12 +66,19 @@ impl Command for Dns {
)
.await
}
- ("custom", Some(matches)) => {
- self.set_custom(matches.values_of_lossy("servers")).await
+ Some(("custom", matches)) => {
+ let servers = match matches.values_of_t::<IpAddr>("servers") {
+ Ok(servers) => Some(servers),
+ Err(e) => match e.kind {
+ clap::ErrorKind::ArgumentNotFound => None,
+ _ => e.exit(),
+ },
+ };
+ self.set_custom(servers).await
}
_ => unreachable!("No custom-dns server command given"),
},
- ("get", _) => self.get().await,
+ Some(("get", _)) => self.get().await,
_ => unreachable!("No custom-dns command given"),
}
}
@@ -102,13 +107,17 @@ impl Dns {
Ok(())
}
- async fn set_custom(&self, servers: Option<Vec<String>>) -> Result<()> {
+ async fn set_custom(&self, servers: Option<Vec<IpAddr>>) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let settings = rpc.get_settings(()).await?.into_inner();
rpc.set_dns_options(types::DnsOptions {
state: types::dns_options::DnsState::Custom as i32,
custom_options: Some(types::CustomDnsOptions {
- addresses: servers.unwrap_or_default(),
+ addresses: servers
+ .unwrap_or_default()
+ .into_iter()
+ .map(|a| a.to_string())
+ .collect(),
}),
..settings.tunnel_options.unwrap().dns_options.unwrap()
})
diff --git a/mullvad-cli/src/cmds/lan.rs b/mullvad-cli/src/cmds/lan.rs
index dd84851f33..bd43f88a6b 100644
--- a/mullvad-cli/src/cmds/lan.rs
+++ b/mullvad-cli/src/cmds/lan.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Result};
-use clap::value_t_or_exit;
pub struct Lan;
@@ -9,28 +8,25 @@ impl Command for Lan {
"lan"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Control the allow local network sharing setting")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
- .about("Change allow LAN setting")
- .arg(
- clap::Arg::with_name("policy")
- .required(true)
- .possible_values(&["allow", "block"]),
- ),
+ clap::App::new("set").about("Change allow LAN setting").arg(
+ clap::Arg::new("policy")
+ .required(true)
+ .possible_values(&["allow", "block"]),
+ ),
)
.subcommand(
- clap::SubCommand::with_name("get")
- .about("Display the current local network sharing setting"),
+ clap::App::new("get").about("Display the current local network sharing setting"),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
if let Some(set_matches) = matches.subcommand_matches("set") {
- let allow_lan = value_t_or_exit!(set_matches.value_of("policy"), String);
+ let allow_lan = set_matches.value_of("policy").expect("missing policy");
self.set(allow_lan == "allow").await
} else if let Some(_matches) = matches.subcommand_matches("get") {
self.get().await
diff --git a/mullvad-cli/src/cmds/reconnect.rs b/mullvad-cli/src/cmds/reconnect.rs
index 87de63144f..c2a577a212 100644
--- a/mullvad-cli/src/cmds/reconnect.rs
+++ b/mullvad-cli/src/cmds/reconnect.rs
@@ -10,18 +10,18 @@ impl Command for Reconnect {
"reconnect"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Command the client to reconnect")
.arg(
- clap::Arg::with_name("wait")
+ clap::Arg::new("wait")
.long("wait")
- .short("w")
+ .short('w')
.help("Wait until reconnected before exiting"),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let receiver_option = if matches.is_present("wait") {
diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs
index 28baab3062..8cb9fa111b 100644
--- a/mullvad-cli/src/cmds/relay.rs
+++ b/mullvad-cli/src/cmds/relay.rs
@@ -1,5 +1,4 @@
use crate::{location, new_rpc_client, Command, Error, Result};
-use clap::{value_t, values_t};
use itertools::Itertools;
use std::{
convert::TryFrom,
@@ -20,49 +19,49 @@ impl Command for Relay {
"relay"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Manage relay and tunnel constraints")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("set")
+ clap::App::new("set")
.about(
"Set relay server selection parameters. Such as location and port/protocol",
)
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("custom")
+ clap::App::new("custom")
.about("Set a custom VPN relay")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("wireguard")
+ .subcommand(clap::App::new("wireguard")
.arg(
- clap::Arg::with_name("host")
+ clap::Arg::new("host")
.help("Hostname or IP")
.required(true),
)
.arg(
- clap::Arg::with_name("port")
+ clap::Arg::new("port")
.help("Remote network port")
.required(true),
)
.arg(
- clap::Arg::with_name("peer-pubkey")
+ clap::Arg::new("peer-pubkey")
.help("Base64 encoded peer public key")
.required(true),
)
.arg(
- clap::Arg::with_name("v4-gateway")
+ clap::Arg::new("v4-gateway")
.help("IPv4 gateway address")
.required(true),
)
.arg(
- clap::Arg::with_name("addr")
+ clap::Arg::new("addr")
.help("Local address of wireguard tunnel")
.required(true)
- .multiple(true),
+ .multiple_values(true),
)
.arg(
- clap::Arg::with_name("protocol")
+ clap::Arg::new("protocol")
.help("Transport protocol. If TCP is selected, traffic is \
sent over TCP using a udp-over-tcp proxy")
.long("protocol")
@@ -70,35 +69,35 @@ impl Command for Relay {
.possible_values(&["udp", "tcp"]),
)
.arg(
- clap::Arg::with_name("v6-gateway")
+ clap::Arg::new("v6-gateway")
.help("IPv6 gateway address")
.long("v6-gateway")
.takes_value(true),
)
)
- .subcommand(clap::SubCommand::with_name("openvpn")
+ .subcommand(clap::App::new("openvpn")
.arg(
- clap::Arg::with_name("host")
+ clap::Arg::new("host")
.help("Hostname or IP")
.required(true),
)
.arg(
- clap::Arg::with_name("port")
+ clap::Arg::new("port")
.help("Remote network port")
.required(true),
)
.arg(
- clap::Arg::with_name("username")
+ clap::Arg::new("username")
.help("Username to be used with the OpenVpn relay")
.required(true),
)
.arg(
- clap::Arg::with_name("password")
+ clap::Arg::new("password")
.help("Password to be used with the OpenVpn relay")
.required(true),
)
.arg(
- clap::Arg::with_name("protocol")
+ clap::Arg::new("protocol")
.help("Transport protocol")
.long("protocol")
.default_value("udp")
@@ -112,42 +111,42 @@ impl Command for Relay {
command to show available alternatives.")
)
.subcommand(
- clap::SubCommand::with_name("hostname")
+ clap::App::new("hostname")
.about("Set the exact relay to use via its hostname. Shortcut for \
'location <country> <city> <hostname>'.")
.arg(
- clap::Arg::with_name("hostname")
+ clap::Arg::new("hostname")
.help("The hostname")
.required(true),
),
)
.subcommand(
- clap::SubCommand::with_name("provider")
+ clap::App::new("provider")
.about("Set hosting provider(s) to select relays from. The 'list' \
command shows the available relays and their providers.")
.arg(
- clap::Arg::with_name("provider")
+ clap::Arg::new("provider")
.help("The hosting provider(s) to use, or 'any' for no preference.")
- .multiple(true)
+ .multiple_values(true)
.required(true)
)
)
.subcommand(
- clap::SubCommand::with_name("tunnel")
+ clap::App::new("tunnel")
.about("Set tunnel protocol-specific constraints.")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(
- clap::SubCommand::with_name("openvpn")
+ clap::App::new("openvpn")
.about("Set OpenVPN-specific constraints")
.setting(clap::AppSettings::ArgRequiredElseHelp)
.arg(
- clap::Arg::with_name("port")
+ clap::Arg::new("port")
.help("Port to use. Either 'any' or a specific port")
.long("port")
.takes_value(true),
)
.arg(
- clap::Arg::with_name("transport protocol")
+ clap::Arg::new("transport protocol")
.help("Transport protocol")
.long("protocol")
.possible_values(&["any", "udp", "tcp"])
@@ -155,17 +154,17 @@ impl Command for Relay {
)
)
.subcommand(
- clap::SubCommand::with_name("wireguard")
+ clap::App::new("wireguard")
.about("Set WireGuard-specific constraints")
.setting(clap::AppSettings::ArgRequiredElseHelp)
.arg(
- clap::Arg::with_name("port")
+ clap::Arg::new("port")
.help("Port to use. Either 'any' or a specific port")
.long("port")
.takes_value(true),
)
.arg(
- clap::Arg::with_name("transport protocol")
+ clap::Arg::new("transport protocol")
.help("Transport protocol. If TCP is selected, traffic is \
sent over TCP using a udp-over-tcp proxy")
.long("protocol")
@@ -173,13 +172,13 @@ impl Command for Relay {
.takes_value(true),
)
.arg(
- clap::Arg::with_name("ip version")
+ clap::Arg::new("ip version")
.long("ipv")
.possible_values(&["any", "4", "6"])
.takes_value(true),
)
.arg(
- clap::Arg::with_name("entry location")
+ clap::Arg::new("entry location")
.help("Entry endpoint to use. This can be 'any', 'none', or \
any location that is valid with 'set location', \
such as 'se got'.")
@@ -189,27 +188,27 @@ impl Command for Relay {
)
)
)
- .subcommand(clap::SubCommand::with_name("tunnel-protocol")
+ .subcommand(clap::App::new("tunnel-protocol")
.about("Set tunnel protocol")
.arg(
- clap::Arg::with_name("tunnel protocol")
+ clap::Arg::new("tunnel protocol")
.required(true)
.index(1)
.possible_values(&["any", "wireguard", "openvpn", ]),
)
),
)
- .subcommand(clap::SubCommand::with_name("get"))
+ .subcommand(clap::App::new("get"))
.subcommand(
- clap::SubCommand::with_name("list").about("List available countries and cities"),
+ clap::App::new("list").about("List available countries and cities"),
)
.subcommand(
- clap::SubCommand::with_name("update")
+ clap::App::new("update")
.about("Update the list of available countries and cities"),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
if let Some(set_matches) = matches.subcommand_matches("set") {
self.set(set_matches).await
} else if matches.subcommand_matches("get").is_some() {
@@ -234,7 +233,7 @@ impl Relay {
Ok(())
}
- async fn set(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set(&self, matches: &clap::ArgMatches) -> Result<()> {
if let Some(custom_matches) = matches.subcommand_matches("custom") {
self.set_custom(custom_matches).await
} else if let Some(location_matches) = matches.subcommand_matches("location") {
@@ -258,11 +257,11 @@ impl Relay {
}
}
- async fn set_custom(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set_custom(&self, matches: &clap::ArgMatches) -> Result<()> {
let custom_endpoint = match matches.subcommand() {
- ("openvpn", Some(openvpn_matches)) => Self::read_custom_openvpn_relay(openvpn_matches),
- ("wireguard", Some(wg_matches)) => Self::read_custom_wireguard_relay(wg_matches),
- (_unknown_tunnel, _) => unreachable!("No set relay command given"),
+ Some(("openvpn", openvpn_matches)) => Self::read_custom_openvpn_relay(openvpn_matches),
+ Some(("wireguard", wg_matches)) => Self::read_custom_wireguard_relay(wg_matches),
+ _ => unreachable!("No set relay command given"),
};
self.update_constraints(types::RelaySettingsUpdate {
@@ -271,12 +270,12 @@ impl Relay {
.await
}
- fn read_custom_openvpn_relay(matches: &clap::ArgMatches<'_>) -> types::CustomRelaySettings {
- let host = value_t!(matches.value_of("host"), String).unwrap_or_else(|e| e.exit());
- let port = value_t!(matches.value_of("port"), u16).unwrap_or_else(|e| e.exit());
- let username = value_t!(matches.value_of("username"), String).unwrap_or_else(|e| e.exit());
- let password = value_t!(matches.value_of("password"), String).unwrap_or_else(|e| e.exit());
- let protocol = value_t!(matches.value_of("protocol"), String).unwrap_or_else(|e| e.exit());
+ fn read_custom_openvpn_relay(matches: &clap::ArgMatches) -> types::CustomRelaySettings {
+ let host = matches.value_of_t_or_exit("host");
+ let port = matches.value_of_t_or_exit("port");
+ let username = matches.value_of_t_or_exit("username");
+ let password = matches.value_of_t_or_exit("password");
+ let protocol: String = matches.value_of_t_or_exit("protocol");
let protocol = Self::validate_transport_protocol(&protocol);
@@ -296,24 +295,22 @@ impl Relay {
}
}
- fn read_custom_wireguard_relay(matches: &clap::ArgMatches<'_>) -> types::CustomRelaySettings {
+ fn read_custom_wireguard_relay(matches: &clap::ArgMatches) -> types::CustomRelaySettings {
use types::connection_config::wireguard_config;
- let host = value_t!(matches.value_of("host"), String).unwrap_or_else(|e| e.exit());
- let port = value_t!(matches.value_of("port"), u16).unwrap_or_else(|e| e.exit());
- let addresses = values_t!(matches.values_of("addr"), IpAddr).unwrap_or_else(|e| e.exit());
- let peer_key_str =
- value_t!(matches.value_of("peer-pubkey"), String).unwrap_or_else(|e| e.exit());
- let ipv4_gateway =
- value_t!(matches.value_of("v4-gateway"), Ipv4Addr).unwrap_or_else(|e| e.exit());
- let ipv6_gateway = match value_t!(matches.value_of("v6-gateway"), Ipv6Addr) {
+ let host = matches.value_of_t_or_exit("host");
+ let port = matches.value_of_t_or_exit("port");
+ let addresses: Vec<IpAddr> = matches.values_of_t_or_exit("addr");
+ let peer_key_str: String = matches.value_of_t_or_exit("peer-pubkey");
+ let ipv4_gateway: Ipv4Addr = matches.value_of_t_or_exit("v4-gateway");
+ let ipv6_gateway = match matches.value_of_t::<Ipv6Addr>("v6-gateway") {
Ok(gateway) => Some(gateway),
Err(e) => match e.kind {
clap::ErrorKind::ArgumentNotFound => None,
_ => e.exit(),
},
};
- let protocol = value_t!(matches.value_of("protocol"), String).unwrap_or_else(|e| e.exit());
+ let protocol: String = matches.value_of_t_or_exit("protocol");
let protocol = Self::validate_transport_protocol(&protocol);
let mut private_key_str = String::new();
println!("Reading private key from standard input");
@@ -380,15 +377,15 @@ impl Relay {
match protocol {
"udp" => types::TransportProtocol::Udp,
"tcp" => types::TransportProtocol::Tcp,
- _ => clap::Error::with_description(
- "invalid transport protocol",
+ _ => clap::Error::raw(
clap::ErrorKind::ValueValidation,
+ "invalid transport protocol",
)
.exit(),
}
}
- async fn set_hostname(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set_hostname(&self, matches: &clap::ArgMatches) -> Result<()> {
let hostname = matches.value_of("hostname").unwrap();
let countries = Self::get_filtered_relays().await?;
@@ -425,15 +422,11 @@ impl Relay {
})
.await
} else {
- clap::Error::with_description(
- "No matching server found",
- clap::ErrorKind::ValueValidation,
- )
- .exit()
+ clap::Error::raw(clap::ErrorKind::ValueValidation, "No matching server found").exit()
}
}
- async fn set_location(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set_location(&self, matches: &clap::ArgMatches) -> Result<()> {
let location_constraint = location::get_constraint_from_args(matches);
let mut found = false;
@@ -490,10 +483,8 @@ impl Relay {
.await
}
- async fn set_providers(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
- let providers =
- values_t!(matches.values_of("provider"), String).unwrap_or_else(|e| e.exit());
-
+ async fn set_providers(&self, matches: &clap::ArgMatches) -> Result<()> {
+ let providers: Vec<String> = matches.values_of_t_or_exit("provider");
let providers = if providers.iter().next().map(String::as_str) == Some("any") {
vec![]
} else {
@@ -511,7 +502,7 @@ impl Relay {
.await
}
- async fn set_openvpn_constraints(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set_openvpn_constraints(&self, matches: &clap::ArgMatches) -> Result<()> {
let mut openvpn_constraints = {
let mut rpc = new_rpc_client().await?;
self.get_openvpn_constraints(&mut rpc).await?
@@ -552,7 +543,7 @@ impl Relay {
}
}
- async fn set_wireguard_constraints(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set_wireguard_constraints(&self, matches: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let mut wireguard_constraints = self.get_wireguard_constraints(&mut rpc).await?;
@@ -606,7 +597,7 @@ impl Relay {
}
}
- async fn set_tunnel_protocol(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn set_tunnel_protocol(&self, matches: &clap::ArgMatches) -> Result<()> {
let tunnel_type = match matches.value_of("tunnel protocol").unwrap() {
"wireguard" => Some(types::TunnelType::Wireguard),
"openvpn" => Some(types::TunnelType::Openvpn),
@@ -775,7 +766,7 @@ fn parse_entry_location_constraint<'a, T: Iterator<Item = &'a str>>(
}
fn parse_transport_port(
- matches: &clap::ArgMatches<'_>,
+ matches: &clap::ArgMatches,
current_constraint: &mut Option<types::TransportPort>,
) -> Result<Option<types::TransportPort>> {
let protocol = match matches.value_of("transport protocol") {
diff --git a/mullvad-cli/src/cmds/reset.rs b/mullvad-cli/src/cmds/reset.rs
index 963f62e005..c4cd3a8625 100644
--- a/mullvad-cli/src/cmds/reset.rs
+++ b/mullvad-cli/src/cmds/reset.rs
@@ -8,11 +8,11 @@ impl Command for Reset {
"factory-reset"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name()).about("Reset settings, caches and logs")
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name()).about("Reset settings, caches and logs")
}
- async fn run(&self, _: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, _: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
if Self::receive_confirmation() {
rpc.factory_reset(())
diff --git a/mullvad-cli/src/cmds/split_tunnel/linux.rs b/mullvad-cli/src/cmds/split_tunnel/linux.rs
index f9945d14d6..3480f27fb0 100644
--- a/mullvad-cli/src/cmds/split_tunnel/linux.rs
+++ b/mullvad-cli/src/cmds/split_tunnel/linux.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Result};
-use clap::value_t_or_exit;
pub struct SplitTunnel;
@@ -9,8 +8,8 @@ impl Command for SplitTunnel {
"split-tunnel"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about(
"Manage split tunneling. To launch applications outside \
the tunnel, use the program 'mullvad-exclude'.",
@@ -19,55 +18,51 @@ impl Command for SplitTunnel {
.subcommand(create_pid_subcommand())
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("pid", Some(pid_matches)) => Self::handle_pid_cmd(pid_matches).await,
+ Some(("pid", pid_matches)) => Self::handle_pid_cmd(pid_matches).await,
_ => unreachable!("unhandled comand"),
}
}
}
-fn create_pid_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("pid")
+fn create_pid_subcommand() -> clap::App<'static> {
+ clap::App::new("pid")
.about("Manage processes to exclude from the tunnel")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(
- clap::SubCommand::with_name("add").arg(clap::Arg::with_name("pid").required(true)),
- )
- .subcommand(
- clap::SubCommand::with_name("delete").arg(clap::Arg::with_name("pid").required(true)),
- )
- .subcommand(clap::SubCommand::with_name("clear"))
- .subcommand(clap::SubCommand::with_name("list"))
+ .subcommand(clap::App::new("add").arg(clap::Arg::new("pid").required(true)))
+ .subcommand(clap::App::new("delete").arg(clap::Arg::new("pid").required(true)))
+ .subcommand(clap::App::new("clear"))
+ .subcommand(clap::App::new("list"))
}
impl SplitTunnel {
- async fn handle_pid_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_pid_cmd(matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("add", Some(matches)) => {
- let pid = value_t_or_exit!(matches.value_of("pid"), i32);
+ Some(("add", matches)) => {
+ let pid: i32 = matches.value_of_t_or_exit("pid");
new_rpc_client()
.await?
.add_split_tunnel_process(pid)
.await?;
Ok(())
}
- ("delete", Some(matches)) => {
- let pid = value_t_or_exit!(matches.value_of("pid"), i32);
+ Some(("delete", matches)) => {
+ let pid: i32 = matches.value_of_t_or_exit("pid");
new_rpc_client()
.await?
.remove_split_tunnel_process(pid)
.await?;
Ok(())
}
- ("clear", Some(_)) => {
+ Some(("clear", _)) => {
new_rpc_client()
.await?
.clear_split_tunnel_processes(())
.await?;
Ok(())
}
- ("list", Some(_)) => {
+ Some(("list", _)) => {
let mut pids_stream = new_rpc_client()
.await?
.get_split_tunnel_processes(())
diff --git a/mullvad-cli/src/cmds/split_tunnel/windows.rs b/mullvad-cli/src/cmds/split_tunnel/windows.rs
index 402186a77c..0bc8d468bc 100644
--- a/mullvad-cli/src/cmds/split_tunnel/windows.rs
+++ b/mullvad-cli/src/cmds/split_tunnel/windows.rs
@@ -1,5 +1,4 @@
use crate::{new_rpc_client, Command, Result};
-use clap::value_t_or_exit;
pub struct SplitTunnel;
@@ -9,29 +8,29 @@ impl Command for SplitTunnel {
"split-tunnel"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Set options for applications to exclude from the tunnel")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_app_subcommand())
.subcommand(
- clap::SubCommand::with_name("set")
+ clap::App::new("set")
.about("Enable or disable split tunnel")
.arg(
- clap::Arg::with_name("policy")
+ clap::Arg::new("policy")
.required(true)
.possible_values(&["on", "off"]),
),
)
- .subcommand(clap::SubCommand::with_name("get").about("Display the split tunnel status"))
+ .subcommand(clap::App::new("get").about("Display the split tunnel status"))
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("app", Some(matches)) => Self::handle_app_subcommand(matches).await,
- ("get", _) => self.get().await,
- ("set", Some(matches)) => {
- let enabled = value_t_or_exit!(matches.value_of("policy"), String);
+ Some(("app", matches)) => Self::handle_app_subcommand(matches).await,
+ Some(("get", _)) => self.get().await,
+ Some(("set", matches)) => {
+ let enabled = matches.value_of("policy").expect("missing policy");
self.set(enabled == "on").await
}
_ => {
@@ -41,24 +40,20 @@ impl Command for SplitTunnel {
}
}
-fn create_app_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("app")
+fn create_app_subcommand() -> clap::App<'static> {
+ clap::App::new("app")
.about("Manage applications to exclude from the tunnel")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("list"))
- .subcommand(
- clap::SubCommand::with_name("add").arg(clap::Arg::with_name("path").required(true)),
- )
- .subcommand(
- clap::SubCommand::with_name("remove").arg(clap::Arg::with_name("path").required(true)),
- )
- .subcommand(clap::SubCommand::with_name("clear"))
+ .subcommand(clap::App::new("list"))
+ .subcommand(clap::App::new("add").arg(clap::Arg::new("path").required(true)))
+ .subcommand(clap::App::new("remove").arg(clap::Arg::new("path").required(true)))
+ .subcommand(clap::App::new("clear"))
}
impl SplitTunnel {
- async fn handle_app_subcommand(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_app_subcommand(matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("list", Some(_)) => {
+ Some(("list", _)) => {
let paths = new_rpc_client()
.await?
.get_settings(())
@@ -75,20 +70,20 @@ impl SplitTunnel {
Ok(())
}
- ("add", Some(matches)) => {
- let path = value_t_or_exit!(matches.value_of("path"), String);
+ Some(("add", matches)) => {
+ let path: String = matches.value_of_t_or_exit("path");
new_rpc_client().await?.add_split_tunnel_app(path).await?;
Ok(())
}
- ("remove", Some(matches)) => {
- let path = value_t_or_exit!(matches.value_of("path"), String);
+ Some(("remove", matches)) => {
+ let path: String = matches.value_of_t_or_exit("path");
new_rpc_client()
.await?
.remove_split_tunnel_app(path)
.await?;
Ok(())
}
- ("clear", Some(_)) => {
+ Some(("clear", _)) => {
new_rpc_client().await?.clear_split_tunnel_apps(()).await?;
Ok(())
}
diff --git a/mullvad-cli/src/cmds/status.rs b/mullvad-cli/src/cmds/status.rs
index f4e943cb3c..8c4a929c30 100644
--- a/mullvad-cli/src/cmds/status.rs
+++ b/mullvad-cli/src/cmds/status.rs
@@ -11,27 +11,27 @@ impl Command for Status {
"status"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("View the state of the VPN tunnel")
.arg(
- clap::Arg::with_name("location")
+ clap::Arg::new("location")
.long("location")
- .short("l")
+ .short('l')
.help("Prints the current location and IP. Based on GeoIP lookups"),
)
.subcommand(
- clap::SubCommand::with_name("listen")
+ clap::App::new("listen")
.about("Listen for VPN tunnel state changes")
.arg(
- clap::Arg::with_name("verbose")
- .short("v")
+ clap::Arg::new("verbose")
+ .short('v')
.help("Enables verbose output"),
),
)
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let state = rpc.get_tunnel_state(()).await?.into_inner();
diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs
index 6d7be54514..f3b218648e 100644
--- a/mullvad-cli/src/cmds/tunnel.rs
+++ b/mullvad-cli/src/cmds/tunnel.rs
@@ -1,5 +1,4 @@
use crate::{format::print_keygen_event, new_rpc_client, Command, Error, Result};
-use clap::value_t;
use mullvad_management_interface::types::{self, Timestamp, TunnelOptions};
use mullvad_types::wireguard::DEFAULT_ROTATION_INTERVAL;
use std::{convert::TryFrom, time::Duration};
@@ -12,8 +11,8 @@ impl Command for Tunnel {
"tunnel"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Manage tunnel specific options")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_openvpn_subcommand())
@@ -21,11 +20,11 @@ impl Command for Tunnel {
.subcommand(create_ipv6_subcommand())
}
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("openvpn", Some(openvpn_matches)) => Self::handle_openvpn_cmd(openvpn_matches).await,
- ("wireguard", Some(wg_matches)) => Self::handle_wireguard_cmd(wg_matches).await,
- ("ipv6", Some(ipv6_matches)) => Self::handle_ipv6_cmd(ipv6_matches).await,
+ Some(("openvpn", openvpn_matches)) => Self::handle_openvpn_cmd(openvpn_matches).await,
+ Some(("wireguard", wg_matches)) => Self::handle_wireguard_cmd(wg_matches).await,
+ Some(("ipv6", ipv6_matches)) => Self::handle_ipv6_cmd(ipv6_matches).await,
_ => {
unreachable!("unhandled comand");
}
@@ -33,8 +32,8 @@ impl Command for Tunnel {
}
}
-fn create_wireguard_subcommand() -> clap::App<'static, 'static> {
- let subcmd = clap::SubCommand::with_name("wireguard")
+fn create_wireguard_subcommand() -> clap::App<'static> {
+ let subcmd = clap::App::new("wireguard")
.about("Manage options for Wireguard tunnels")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_wireguard_mtu_subcommand())
@@ -49,35 +48,33 @@ fn create_wireguard_subcommand() -> clap::App<'static, 'static> {
}
}
-fn create_wireguard_mtu_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("mtu")
+fn create_wireguard_mtu_subcommand() -> clap::App<'static> {
+ clap::App::new("mtu")
.about("Configure the MTU of the wireguard tunnel")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("get"))
- .subcommand(clap::SubCommand::with_name("unset"))
- .subcommand(
- clap::SubCommand::with_name("set").arg(clap::Arg::with_name("mtu").required(true)),
- )
+ .subcommand(clap::App::new("get"))
+ .subcommand(clap::App::new("unset"))
+ .subcommand(clap::App::new("set").arg(clap::Arg::new("mtu").required(true)))
}
-fn create_wireguard_keys_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("key")
+fn create_wireguard_keys_subcommand() -> clap::App<'static> {
+ clap::App::new("key")
.about("Manage your wireguard key")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("check"))
- .subcommand(clap::SubCommand::with_name("regenerate"))
+ .subcommand(clap::App::new("check"))
+ .subcommand(clap::App::new("regenerate"))
.subcommand(create_wireguard_keys_rotation_interval_subcommand())
}
#[cfg(windows)]
-fn create_wireguard_use_wg_nt_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("use-wireguard-nt")
+fn create_wireguard_use_wg_nt_subcommand() -> clap::App<'static> {
+ clap::App::new("use-wireguard-nt")
.about("Enable or disable wireguard-nt")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("get"))
+ .subcommand(clap::App::new("get"))
.subcommand(
- clap::SubCommand::with_name("set").arg(
- clap::Arg::with_name("policy")
+ clap::App::new("set").arg(
+ clap::Arg::new("policy")
.required(true)
.takes_value(true)
.possible_values(&["on", "off"]),
@@ -85,42 +82,38 @@ fn create_wireguard_use_wg_nt_subcommand() -> clap::App<'static, 'static> {
)
}
-fn create_wireguard_keys_rotation_interval_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("rotation-interval")
+fn create_wireguard_keys_rotation_interval_subcommand() -> clap::App<'static> {
+ clap::App::new("rotation-interval")
.about("Manage automatic key rotation (given in hours)")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("get"))
- .subcommand(clap::SubCommand::with_name("reset").about("Use the default rotation interval"))
- .subcommand(
- clap::SubCommand::with_name("set").arg(clap::Arg::with_name("interval").required(true)),
- )
+ .subcommand(clap::App::new("get"))
+ .subcommand(clap::App::new("reset").about("Use the default rotation interval"))
+ .subcommand(clap::App::new("set").arg(clap::Arg::new("interval").required(true)))
}
-fn create_openvpn_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("openvpn")
+fn create_openvpn_subcommand() -> clap::App<'static> {
+ clap::App::new("openvpn")
.about("Manage options for OpenVPN tunnels")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
.subcommand(create_openvpn_mssfix_subcommand())
}
-fn create_openvpn_mssfix_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("mssfix")
+fn create_openvpn_mssfix_subcommand() -> clap::App<'static> {
+ clap::App::new("mssfix")
.about("Configure the optional mssfix parameter")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("get"))
- .subcommand(clap::SubCommand::with_name("unset"))
- .subcommand(
- clap::SubCommand::with_name("set").arg(clap::Arg::with_name("mssfix").required(true)),
- )
+ .subcommand(clap::App::new("get"))
+ .subcommand(clap::App::new("unset"))
+ .subcommand(clap::App::new("set").arg(clap::Arg::new("mssfix").required(true)))
}
-fn create_ipv6_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("ipv6")
+fn create_ipv6_subcommand() -> clap::App<'static> {
+ clap::App::new("ipv6")
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .subcommand(clap::SubCommand::with_name("get"))
+ .subcommand(clap::App::new("get"))
.subcommand(
- clap::SubCommand::with_name("set").arg(
- clap::Arg::with_name("policy")
+ clap::App::new("set").arg(
+ clap::Arg::new("policy")
.required(true)
.takes_value(true)
.possible_values(&["on", "off"]),
@@ -129,51 +122,51 @@ fn create_ipv6_subcommand() -> clap::App<'static, 'static> {
}
impl Tunnel {
- async fn handle_openvpn_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_openvpn_cmd(matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("mssfix", Some(mssfix_matches)) => {
+ Some(("mssfix", mssfix_matches)) => {
Self::handle_openvpn_mssfix_cmd(mssfix_matches).await
}
_ => unreachable!("unhandled command"),
}
}
- async fn handle_openvpn_mssfix_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_openvpn_mssfix_cmd(matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("get", Some(_)) => Self::process_openvpn_mssfix_get().await,
- ("unset", Some(_)) => Self::process_openvpn_mssfix_unset().await,
- ("set", Some(set_matches)) => Self::process_openvpn_mssfix_set(set_matches).await,
+ Some(("get", _)) => Self::process_openvpn_mssfix_get().await,
+ Some(("unset", _)) => Self::process_openvpn_mssfix_unset().await,
+ Some(("set", set_matches)) => Self::process_openvpn_mssfix_set(set_matches).await,
_ => unreachable!("unhandled command"),
}
}
- async fn handle_wireguard_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_wireguard_cmd(matches: &clap::ArgMatches) -> Result<()> {
match matches.subcommand() {
- ("mtu", Some(matches)) => match matches.subcommand() {
- ("get", _) => Self::process_wireguard_mtu_get().await,
- ("set", Some(matches)) => Self::process_wireguard_mtu_set(matches).await,
- ("unset", _) => Self::process_wireguard_mtu_unset().await,
+ Some(("mtu", matches)) => match matches.subcommand() {
+ Some(("get", _)) => Self::process_wireguard_mtu_get().await,
+ Some(("set", matches)) => Self::process_wireguard_mtu_set(matches).await,
+ Some(("unset", _)) => Self::process_wireguard_mtu_unset().await,
_ => unreachable!("unhandled command"),
},
- ("key", Some(matches)) => match matches.subcommand() {
- ("check", _) => Self::process_wireguard_key_check().await,
- ("regenerate", _) => Self::process_wireguard_key_generate().await,
- ("rotation-interval", Some(matches)) => match matches.subcommand() {
- ("get", _) => Self::process_wireguard_rotation_interval_get().await,
- ("set", Some(matches)) => {
+ Some(("key", matches)) => match matches.subcommand() {
+ Some(("check", _)) => Self::process_wireguard_key_check().await,
+ Some(("regenerate", _)) => Self::process_wireguard_key_generate().await,
+ Some(("rotation-interval", matches)) => match matches.subcommand() {
+ Some(("get", _)) => Self::process_wireguard_rotation_interval_get().await,
+ Some(("set", matches)) => {
Self::process_wireguard_rotation_interval_set(matches).await
}
- ("reset", _) => Self::process_wireguard_rotation_interval_reset().await,
+ Some(("reset", _)) => Self::process_wireguard_rotation_interval_reset().await,
_ => unreachable!("unhandled command"),
},
_ => unreachable!("unhandled command"),
},
#[cfg(windows)]
- ("use-wireguard-nt", Some(matches)) => match matches.subcommand() {
- ("get", _) => Self::process_wireguard_use_wg_nt_get().await,
- ("set", Some(matches)) => Self::process_wireguard_use_wg_nt_set(matches).await,
+ Some(("use-wireguard-nt", matches)) => match matches.subcommand() {
+ Some(("get", _)) => Self::process_wireguard_use_wg_nt_get().await,
+ Some(("set", matches)) => Self::process_wireguard_use_wg_nt_set(matches).await,
_ => unreachable!("unhandled command"),
},
@@ -195,8 +188,8 @@ impl Tunnel {
Ok(())
}
- async fn process_wireguard_mtu_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
- let mtu = value_t!(matches.value_of("mtu"), u16).unwrap_or_else(|e| e.exit());
+ async fn process_wireguard_mtu_set(matches: &clap::ArgMatches) -> Result<()> {
+ let mtu = matches.value_of_t_or_exit::<u16>("mtu");
let mut rpc = new_rpc_client().await?;
rpc.set_wireguard_mtu(mtu as u32).await?;
println!("Wireguard MTU has been updated");
@@ -222,7 +215,7 @@ impl Tunnel {
}
#[cfg(windows)]
- async fn process_wireguard_use_wg_nt_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn process_wireguard_use_wg_nt_set(matches: &clap::ArgMatches) -> Result<()> {
let new_state = matches.value_of("policy").unwrap() == "on";
let mut rpc = new_rpc_client().await?;
rpc.set_use_wireguard_nt(new_state).await?;
@@ -285,9 +278,8 @@ impl Tunnel {
Ok(())
}
- async fn process_wireguard_rotation_interval_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
- let rotate_interval =
- value_t!(matches.value_of("interval"), u64).unwrap_or_else(|e| e.exit());
+ async fn process_wireguard_rotation_interval_set(matches: &clap::ArgMatches) -> Result<()> {
+ let rotate_interval = matches.value_of_t_or_exit::<u64>("interval");
let mut rpc = new_rpc_client().await?;
rpc.set_wireguard_rotation_interval(types::Duration::from(Duration::from_secs(
60 * 60 * rotate_interval,
@@ -307,7 +299,7 @@ impl Tunnel {
Ok(())
}
- async fn handle_ipv6_cmd(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn handle_ipv6_cmd(matches: &clap::ArgMatches) -> Result<()> {
if matches.subcommand_matches("get").is_some() {
Self::process_ipv6_get().await
} else if let Some(m) = matches.subcommand_matches("set") {
@@ -348,8 +340,8 @@ impl Tunnel {
Ok(())
}
- async fn process_openvpn_mssfix_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
- let new_value = value_t!(matches.value_of("mssfix"), u16).unwrap_or_else(|e| e.exit());
+ async fn process_openvpn_mssfix_set(matches: &clap::ArgMatches) -> Result<()> {
+ let new_value = matches.value_of_t_or_exit::<u16>("mssfix");
let mut rpc = new_rpc_client().await?;
rpc.set_openvpn_mssfix(new_value as u32).await?;
println!("mssfix parameter has been updated");
@@ -369,7 +361,7 @@ impl Tunnel {
Ok(())
}
- async fn process_ipv6_set(matches: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn process_ipv6_set(matches: &clap::ArgMatches) -> Result<()> {
let enabled = matches.value_of("policy").unwrap() == "on";
let mut rpc = new_rpc_client().await?;
diff --git a/mullvad-cli/src/cmds/version.rs b/mullvad-cli/src/cmds/version.rs
index 08944f921b..cec13834da 100644
--- a/mullvad-cli/src/cmds/version.rs
+++ b/mullvad-cli/src/cmds/version.rs
@@ -8,12 +8,12 @@ impl Command for Version {
"version"
}
- fn clap_subcommand(&self) -> clap::App<'static, 'static> {
- clap::SubCommand::with_name(self.name())
+ fn clap_subcommand(&self) -> clap::App<'static> {
+ clap::App::new(self.name())
.about("Shows current version, and the currently supported versions")
}
- async fn run(&self, _: &clap::ArgMatches<'_>) -> Result<()> {
+ async fn run(&self, _: &clap::ArgMatches) -> Result<()> {
let mut rpc = new_rpc_client().await?;
let current_version = rpc
.get_current_version(())
diff --git a/mullvad-cli/src/location.rs b/mullvad-cli/src/location.rs
index e4719f7d37..2fff68998c 100644
--- a/mullvad-cli/src/location.rs
+++ b/mullvad-cli/src/location.rs
@@ -1,28 +1,24 @@
use mullvad_management_interface::types::RelayLocation;
-pub fn get_subcommand() -> clap::App<'static, 'static> {
- clap::SubCommand::with_name("location")
+pub fn get_subcommand() -> clap::App<'static> {
+ clap::App::new("location")
.arg(
- clap::Arg::with_name("country")
+ clap::Arg::new("country")
.help("The two letter country code, or 'any' for no preference.")
.required(true)
.index(1)
.validator(country_code_validator),
)
.arg(
- clap::Arg::with_name("city")
+ clap::Arg::new("city")
.help("The three letter city code")
.index(2)
.validator(city_code_validator),
)
- .arg(
- clap::Arg::with_name("hostname")
- .help("The hostname")
- .index(3),
- )
+ .arg(clap::Arg::new("hostname").help("The hostname").index(3))
}
-pub fn get_constraint_from_args(matches: &clap::ArgMatches<'_>) -> RelayLocation {
+pub fn get_constraint_from_args(matches: &clap::ArgMatches) -> RelayLocation {
let country = matches.value_of("country").unwrap();
let city = matches.value_of("city");
let hostname = matches.value_of("hostname");
@@ -41,9 +37,9 @@ pub fn get_constraint<T: AsRef<str>>(
match (country_original, city, hostname) {
("any", None, None) => RelayLocation::default(),
- ("any", ..) => clap::Error::with_description(
- "City can't be given when selecting 'any' country",
+ ("any", ..) => clap::Error::raw(
clap::ErrorKind::InvalidValue,
+ "City can't be given when selecting 'any' country",
)
.exit(),
(_, None, None) => RelayLocation {
@@ -60,24 +56,24 @@ pub fn get_constraint<T: AsRef<str>>(
city,
hostname,
},
- (..) => clap::Error::with_description(
- "Invalid country, city and hostname combination given",
+ (..) => clap::Error::raw(
clap::ErrorKind::InvalidValue,
+ "Invalid country, city and hostname combination given",
)
.exit(),
}
}
-pub fn country_code_validator<T: AsRef<str>>(code: T) -> std::result::Result<(), String> {
- if code.as_ref().len() == 2 || code.as_ref() == "any" {
+pub fn country_code_validator(code: &str) -> std::result::Result<(), String> {
+ if code.len() == 2 || code == "any" {
Ok(())
} else {
Err(String::from("Country codes must be two letters, or 'any'."))
}
}
-pub fn city_code_validator<T: AsRef<str>>(code: T) -> std::result::Result<(), String> {
- if code.as_ref().len() == 3 {
+pub fn city_code_validator(code: &str) -> std::result::Result<(), String> {
+ if code.len() == 3 {
Ok(())
} else {
Err(String::from("City codes must be three letters"))
diff --git a/mullvad-cli/src/main.rs b/mullvad-cli/src/main.rs
index 766fb43bad..55a195cdb8 100644
--- a/mullvad-cli/src/main.rs
+++ b/mullvad-cli/src/main.rs
@@ -1,6 +1,8 @@
#![deny(rust_2018_idioms)]
use clap::{crate_authors, crate_description};
+#[cfg(all(unix, not(target_os = "android")))]
+use clap_complete::{generator::generate_to, Shell};
use mullvad_management_interface::async_trait;
use std::{collections::HashMap, io};
use talpid_types::ErrorExt;
@@ -43,6 +45,10 @@ pub enum Error {
#[error(display = "Failed to listen for status updates")]
StatusListenerFailed,
+
+ //#[cfg(all(unix, not(target_os = "android"))
+ #[error(display = "Failed to generate shell completions")]
+ CompletionsError(#[error(source, no_from)] io::Error),
}
#[tokio::main]
@@ -74,17 +80,19 @@ async fn run() -> Result<()> {
let commands = cmds::get_commands();
let app = build_cli(&commands);
+ #[cfg(all(unix, not(target_os = "android")))]
let app = app.subcommand(
- clap::SubCommand::with_name("shell-completions")
+ clap::App::new("shell-completions")
.about("Generates completion scripts for your shell")
.arg(
- clap::Arg::with_name("SHELL")
+ clap::Arg::new("SHELL")
.required(true)
- .possible_values(&clap::Shell::variants()[..])
+ .possible_values(Shell::possible_values())
.help("The shell to generate the script for"),
)
.arg(
- clap::Arg::with_name("DIR")
+ clap::Arg::new("DIR")
+ .allow_invalid_utf8(true)
.default_value("./")
.help("Output directory where the shell completions are written"),
)
@@ -93,39 +101,40 @@ async fn run() -> Result<()> {
let app_matches = app.get_matches();
match app_matches.subcommand() {
- ("shell-completions", Some(sub_matches)) => {
- let shell = sub_matches
+ #[cfg(all(unix, not(target_os = "android")))]
+ Some(("shell-completions", sub_matches)) => {
+ let shell: Shell = sub_matches
.value_of("SHELL")
.unwrap()
.parse()
.expect("Invalid shell");
let out_dir = sub_matches.value_of_os("DIR").unwrap();
- build_cli(&commands).gen_completions(BIN_NAME, shell, out_dir);
- Ok(())
+ let mut app = build_cli(&commands);
+ generate_to(shell, &mut app, BIN_NAME, out_dir)
+ .map(|_output_file| ())
+ .map_err(Error::CompletionsError)
}
- (sub_name, Some(sub_matches)) => {
+ Some((sub_name, sub_matches)) => {
if let Some(cmd) = commands.get(sub_name) {
cmd.run(sub_matches).await
} else {
unreachable!("No command matched");
}
}
- (_, None) => {
+ _ => {
unreachable!("No subcommand matches");
}
}
}
-fn build_cli(commands: &HashMap<&'static str, Box<dyn Command>>) -> clap::App<'static, 'static> {
+fn build_cli(commands: &HashMap<&'static str, Box<dyn Command>>) -> clap::App<'static> {
clap::App::new(BIN_NAME)
.version(PRODUCT_VERSION)
.author(crate_authors!())
.about(crate_description!())
.setting(clap::AppSettings::SubcommandRequiredElseHelp)
- .global_settings(&[
- clap::AppSettings::DisableHelpSubcommand,
- clap::AppSettings::VersionlessSubcommands,
- ])
+ .global_setting(clap::AppSettings::DisableHelpSubcommand)
+ .global_setting(clap::AppSettings::DisableVersionFlag)
.subcommands(commands.values().map(|cmd| cmd.clap_subcommand()))
}
@@ -133,7 +142,7 @@ fn build_cli(commands: &HashMap<&'static str, Box<dyn Command>>) -> clap::App<'s
pub trait Command {
fn name(&self) -> &'static str;
- fn clap_subcommand(&self) -> clap::App<'static, 'static>;
+ fn clap_subcommand(&self) -> clap::App<'static>;
- async fn run(&self, matches: &clap::ArgMatches<'_>) -> Result<()>;
+ async fn run(&self, matches: &clap::ArgMatches) -> Result<()>;
}