diff options
| author | David Lönnhager <david.l@mullvad.net> | 2020-04-17 10:57:22 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2020-04-17 10:57:22 +0200 |
| commit | d718db4b02b7a605e1d344eb718b8f9f28078aac (patch) | |
| tree | 0e9eb7c90d8a63993b4e09df2c5968afe7db505e | |
| parent | 0e23841e5ca9148ef6a52ef2b8d00fccc8b783f3 (diff) | |
| parent | 3d6eef646d35c1fe78fbeb10d6871ab948dae5a4 (diff) | |
| download | mullvadvpn-d718db4b02b7a605e1d344eb718b8f9f28078aac.tar.xz mullvadvpn-d718db4b02b7a605e1d344eb718b8f9f28078aac.zip | |
Merge branch 'add-shell-completion'
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rwxr-xr-x | build.sh | 13 | ||||
| -rwxr-xr-x | dist-assets/pkg-scripts/postinstall | 5 | ||||
| -rwxr-xr-x | dist-assets/uninstall_macos.sh | 9 | ||||
| -rw-r--r-- | gui/tasks/distribution.js | 5 | ||||
| -rw-r--r-- | mullvad-cli/Cargo.toml | 4 | ||||
| -rw-r--r-- | mullvad-cli/src/main.rs | 62 |
8 files changed, 86 insertions, 16 deletions
diff --git a/.gitignore b/.gitignore index 0e50984ec3..b235a6c73d 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ /dist-assets/openvpn.exe /dist-assets/sslocal /dist-assets/sslocal.exe +/dist-assets/shell-completions/ /windows/**/bin/ /windows/**/*.user /android/keystore.properties diff --git a/CHANGELOG.md b/CHANGELOG.md index 52f350561f..8f81b72df1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ Line wrap the file at 100 chars. Th ## [Unreleased] +### Added +- Add shell completions for the mullvad CLI. + ### Fixed #### Windows - Improve offline detection logic. @@ -134,6 +134,18 @@ fi ./wireguard/build-wireguard-go.sh echo "Building Rust code in release mode using $RUSTC_VERSION..." + +if [[ ("$(uname -s)" == "Darwin") || ("$(uname -s)" == "Linux") ]]; then + pushd mullvad-cli + mkdir -p "$SCRIPT_DIR/dist-assets/shell-completions" + for sh in bash zsh; do + echo "Generating shell completion script for $sh..." + cargo +stable run $CARGO_ARGS --release --features shell-completions -- \ + shell-completions "$sh" "$SCRIPT_DIR/dist-assets/shell-completions/" + done + popd +fi + MULLVAD_ADD_MANIFEST="1" cargo +stable build $CARGO_ARGS --release ################################################################################ @@ -198,7 +210,6 @@ fi ./update-relays.sh - pushd "$SCRIPT_DIR/gui" echo "Installing JavaScript dependencies..." diff --git a/dist-assets/pkg-scripts/postinstall b/dist-assets/pkg-scripts/postinstall index 51283fea35..803e9cf276 100755 --- a/dist-assets/pkg-scripts/postinstall +++ b/dist-assets/pkg-scripts/postinstall @@ -48,6 +48,8 @@ DAEMON_PLIST=$(cat <<-EOM EOM ) +ZSH_COMPLETIONS_DIR="/usr/local/share/zsh/site-functions/" + "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/mullvad-setup" prepare-restart || true pkill -x "Mullvad VPN" || echo "Unable to kill GUI, not running?" @@ -60,3 +62,6 @@ launchctl load -w $DAEMON_PLIST_PATH mkdir -p /usr/local/bin ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/mullvad" /usr/local/bin/mullvad ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/mullvad-problem-report" /usr/local/bin/mullvad-problem-report + +mkdir -p "$ZSH_COMPLETIONS_DIR" +ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/_mullvad" "$ZSH_COMPLETIONS_DIR/_mullvad" diff --git a/dist-assets/uninstall_macos.sh b/dist-assets/uninstall_macos.sh index aec74760b4..9cf33ec5de 100755 --- a/dist-assets/uninstall_macos.sh +++ b/dist-assets/uninstall_macos.sh @@ -18,13 +18,16 @@ DAEMON_PLIST_PATH="/Library/LaunchDaemons/net.mullvad.daemon.plist" sudo launchctl unload -w "$DAEMON_PLIST_PATH" sudo rm -f "$DAEMON_PLIST_PATH" -echo "Removing app from /Applications ..." -sudo rm -rf /Applications/Mullvad\ VPN.app -sudo pkgutil --forget net.mullvad.vpn || true +echo "Removing shell completion symlink ..." +sudo rm -f /usr/local/share/zsh/site-functions/_mullvad echo "Removing CLI symlinks from /usr/local/bin/ ..." sudo rm -f /usr/local/bin/mullvad /usr/local/bin/mullvad-problem-report +echo "Removing app from /Applications ..." +sudo rm -rf /Applications/Mullvad\ VPN.app +sudo pkgutil --forget net.mullvad.vpn || true + read -p "Do you want to delete the log and cache files the app has created? (y/n) " if [[ "$REPLY" =~ [Yy]$ ]]; then sudo rm -rf /var/log/mullvad-vpn /var/root/Library/Caches/mullvad-vpn diff --git a/gui/tasks/distribution.js b/gui/tasks/distribution.js index 85069037a6..0a9a6ad465 100644 --- a/gui/tasks/distribution.js +++ b/gui/tasks/distribution.js @@ -53,6 +53,7 @@ const config = { { from: distAssets('binaries/x86_64-apple-darwin/openvpn'), to: '.' }, { from: distAssets('binaries/x86_64-apple-darwin/sslocal'), to: '.' }, { from: distAssets('uninstall_macos.sh'), to: './uninstall.sh' }, + { from: distAssets('shell-completions/_mullvad'), to: '.' }, ], }, @@ -127,6 +128,8 @@ const config = { '/opt/Mullvad VPN/resources/mullvad-daemon.conf', distAssets('mullvad') + '=/usr/bin/', distAssets('linux/problem-report-link') + '=/usr/bin/mullvad-problem-report', + distAssets('shell-completions/mullvad.bash') + '=/usr/share/bash-completion/completions/mullvad', + distAssets('shell-completions/_mullvad') + '=/usr/local/share/zsh/site-functions/_mullvad', ], afterInstall: distAssets('linux/after-install.sh'), afterRemove: distAssets('linux/after-remove.sh'), @@ -147,6 +150,8 @@ const config = { '/opt/Mullvad VPN/resources/mullvad-daemon.conf', distAssets('mullvad') + '=/usr/bin/', distAssets('linux/problem-report-link') + '=/usr/bin/mullvad-problem-report', + distAssets('shell-completions/mullvad.bash') + '=/usr/share/bash-completion/completions/mullvad', + distAssets('shell-completions/_mullvad') + '=/usr/local/share/zsh/site-functions/_mullvad', ], afterInstall: distAssets('linux/after-install.sh'), afterRemove: distAssets('linux/after-remove.sh'), diff --git a/mullvad-cli/Cargo.toml b/mullvad-cli/Cargo.toml index ec51a613e3..4deb3f5cbf 100644 --- a/mullvad-cli/Cargo.toml +++ b/mullvad-cli/Cargo.toml @@ -7,6 +7,10 @@ license = "GPL-3.0" edition = "2018" publish = false +[features] +default = [] +shell-completions = [] + [[bin]] name = "mullvad" path = "src/main.rs" diff --git a/mullvad-cli/src/main.rs b/mullvad-cli/src/main.rs index b84307c475..3d8d2a4aef 100644 --- a/mullvad-cli/src/main.rs +++ b/mullvad-cli/src/main.rs @@ -1,13 +1,14 @@ #![deny(rust_2018_idioms)] -use clap::{crate_authors, crate_description, crate_name}; +use clap::{crate_authors, crate_description}; use mullvad_ipc_client::{new_standalone_ipc_client, DaemonRpcClient}; -use std::io; +use std::{collections::HashMap, io}; use talpid_types::ErrorExt; mod cmds; mod location; +pub const BIN_NAME: &str = "mullvad"; pub const PRODUCT_VERSION: &str = include_str!(concat!(env!("OUT_DIR"), "/product-version.txt")); pub type Result<T> = std::result::Result<T, Error>; @@ -50,8 +51,53 @@ fn run() -> Result<()> { env_logger::init(); let commands = cmds::get_commands(); + let app = build_cli(&commands); - let app = clap::App::new(crate_name!()) + #[cfg(feature = "shell-completions")] + let app = app.subcommand( + clap::SubCommand::with_name("shell-completions") + .about("Generates completion scripts for your shell") + .arg( + clap::Arg::with_name("SHELL") + .required(true) + .possible_values(&clap::Shell::variants()[..]) + .help("The shell to generate the script for"), + ) + .arg( + clap::Arg::with_name("DIR") + .default_value("./") + .help("Output directory where the shell completions are written"), + ), + ); + + let app_matches = app.get_matches(); + match app_matches.subcommand() { + #[cfg(feature = "shell-completions")] + ("shell-completions", Some(sub_matches)) => { + let 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(()) + } + (sub_name, Some(sub_matches)) => { + if let Some(cmd) = commands.get(sub_name) { + cmd.run(sub_matches) + } else { + unreachable!("No command matched"); + } + } + (_, None) => { + unreachable!("No subcommand matches"); + } + } +} + +fn build_cli(commands: &HashMap<&'static str, Box<dyn Command>>) -> clap::App<'static, 'static> { + clap::App::new(BIN_NAME) .version(PRODUCT_VERSION) .author(crate_authors!()) .about(crate_description!()) @@ -60,15 +106,7 @@ fn run() -> Result<()> { clap::AppSettings::DisableHelpSubcommand, clap::AppSettings::VersionlessSubcommands, ]) - .subcommands(commands.values().map(|cmd| cmd.clap_subcommand())); - - let app_matches = app.get_matches(); - let (subcommand_name, subcommand_matches) = app_matches.subcommand(); - if let Some(cmd) = commands.get(subcommand_name) { - cmd.run(subcommand_matches.expect("No command matched")) - } else { - unreachable!("No command matched"); - } + .subcommands(commands.values().map(|cmd| cmd.clap_subcommand())) } pub trait Command { |
