From bfcfe5b3fa248943fa307f4ce73f52779badbdd6 Mon Sep 17 00:00:00 2001 From: Edvin Malinovskis Date: Wed, 16 Jan 2019 08:51:43 +0000 Subject: [PATCH] Generic Blacklist implementation (#108) --- README.md | 11 +++++--- src/config.rs | 70 +++++++++++++++++++++++++++++++++++---------------- src/main.rs | 22 ++++++++-------- 3 files changed, 67 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 8009dc99..9aca09ec 100644 --- a/README.md +++ b/README.md @@ -110,11 +110,14 @@ Just run `topgrade`. It will run the following steps: Topgrade already runs inside tmux. This is useful when using topgrade on remote systems. * `-c/--cleanup` - Topgrade will instruct package managers to remove old or unused files * `-n/--dry-run` - Print what should be run. -* `--no-system` - Skip the system upgrade phase. -* `--no-git-repos` - Don't pull custom git repositories. -* `--no-emacs` - Don't upgrade Emacs packages or configuration files. +* `--disable system` - Skip the system upgrade phase. +* `--disable git-repos` - Don't pull custom git repositories. +* `--disable emacs` - Don't upgrade Emacs packages or configuration files. * `--no-retry` - Don't ask to retry failed steps. -* `--no-vim` - Don't upgrade Vim/NeoVim packages or configuration files. +* `--disable vim` - Don't upgrade Vim/NeoVim packages or configuration files. +* `--disable gem` - Don't upgrade ruby gems. + +`--disable` flags can also be combined like so: `--disable system vim` ## Customization You can place a configuration file at `~/.config/topgrade.toml` (on macOS `~/Library/Preferences/topgrade.toml`).. Here's an example: diff --git a/src/config.rs b/src/config.rs index 391d1c38..cc435342 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,15 +1,59 @@ use super::error::{Error, ErrorKind}; use directories::BaseDirs; use failure::ResultExt; +use lazy_static::lazy_static; use serde::Deserialize; use shellexpand; -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use std::fs; use structopt::StructOpt; use toml; type Commands = BTreeMap; +lazy_static! { + // While this is used to automatically generate possible value list everywhere in the code, the + // README.md file still needs to be manually updated. + static ref STEPS_MAPPING: HashMap<&'static str, Step> = { + let mut m = HashMap::new(); + + m.insert("system", Step::System); + m.insert("git-repos", Step::GitRepos); + m.insert("vim", Step::Vim); + m.insert("emacs", Step::Emacs); + m.insert("gem", Step::Gem); + + m + }; +} + +#[derive(Debug, Clone, PartialEq)] +pub enum Step { + /// Don't perform system upgrade + System, + /// Don't perform updates on configured git repos + GitRepos, + /// Don't upgrade Vim packages or configuration files + Vim, + /// Don't upgrade Emacs packages or configuration files + Emacs, + /// Don't upgrade ruby gems + Gem, +} + +impl Step { + fn possible_values() -> Vec<&'static str> { + STEPS_MAPPING.keys().cloned().collect() + } +} + +impl std::str::FromStr for Step { + type Err = structopt::clap::Error; + fn from_str(s: &str) -> Result { + Ok(STEPS_MAPPING.get(s).unwrap().clone()) + } +} + #[derive(Deserialize, Default)] pub struct Config { pre_commands: Option, @@ -60,26 +104,6 @@ pub struct Opt { #[structopt(short = "c", long = "cleanup")] pub cleanup: bool, - /// Don't perform system upgrade - #[structopt(long = "no-system")] - pub no_system: bool, - - /// Don't perform updates on configured git repos - #[structopt(long = "no-git-repos")] - pub no_git_repos: bool, - - /// Don't upgrade Emacs packages or configuration files - #[structopt(long = "no-emacs")] - pub no_emacs: bool, - - /// Don't upgrade Vim packages or configuration files - #[structopt(long = "no-vim")] - pub no_vim: bool, - - /// Don't upgrade ruby gems - #[structopt(long = "no-gem")] - pub no_gem: bool, - /// Print what would be done #[structopt(short = "n", long = "dry-run")] pub dry_run: bool, @@ -87,4 +111,8 @@ pub struct Opt { /// Do not ask to retry failed steps #[structopt(long = "no-retry")] pub no_retry: bool, + + /// Do not perform upgrades for the given steps + #[structopt(long = "disable", raw(possible_values = "&Step::possible_values()"))] + pub disable: Vec, } diff --git a/src/main.rs b/src/main.rs index 4e938108..15fb2948 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ mod steps; mod terminal; mod utils; -use self::config::Config; +use self::config::{Config, Step}; use self::error::{Error, ErrorKind}; use self::report::Report; use self::steps::*; @@ -101,7 +101,7 @@ fn run() -> Result<(), Error> { #[cfg(target_os = "linux")] { - if !opt.no_system { + if !opt.disable.contains(&Step::System) { match &distribution { Ok(distribution) => { report.push_result(execute( @@ -130,11 +130,11 @@ fn run() -> Result<(), Error> { #[cfg(unix)] report.push_result(execute(|| unix::run_nix(run_type), opt.no_retry)?); - if !opt.no_emacs { + if !opt.disable.contains(&Step::Emacs) { git_repos.insert(base_dirs.home_dir().join(".emacs.d")); } - if !opt.no_vim { + if !opt.disable.contains(&Step::Vim) { git_repos.insert(base_dirs.home_dir().join(".vim")); git_repos.insert(base_dirs.home_dir().join(".config/nvim")); } @@ -155,7 +155,7 @@ fn run() -> Result<(), Error> { } } - if !opt.no_git_repos { + if !opt.disable.contains(&Step::GitRepos) { if let Some(custom_git_repos) = config.git_repos() { for git_repo in custom_git_repos { git_repos.insert(git_repo); @@ -176,7 +176,7 @@ fn run() -> Result<(), Error> { report.push_result(execute(|| generic::run_rustup(&base_dirs, run_type), opt.no_retry)?); report.push_result(execute(|| generic::run_cargo_update(run_type), opt.no_retry)?); - if !opt.no_emacs { + if !opt.disable.contains(&Step::Emacs) { report.push_result(execute(|| generic::run_emacs(&base_dirs, run_type), opt.no_retry)?); } @@ -185,7 +185,7 @@ fn run() -> Result<(), Error> { report.push_result(execute(|| generic::run_pipx_update(run_type), opt.no_retry)?); report.push_result(execute(|| generic::run_jetpack(run_type), opt.no_retry)?); - if !opt.no_vim { + if !opt.disable.contains(&Step::Vim) { report.push_result(execute(|| vim::upgrade_vim(&base_dirs, run_type), opt.no_retry)?); report.push_result(execute(|| vim::upgrade_neovim(&base_dirs, run_type), opt.no_retry)?); } @@ -205,7 +205,7 @@ fn run() -> Result<(), Error> { )))] report.push_result(execute(|| generic::run_apm(run_type), opt.no_retry)?); - if !opt.no_gem { + if !opt.disable.contains(&Step::Gem) { report.push_result(execute(|| generic::run_gem(&base_dirs, run_type), opt.no_retry)?); } @@ -233,21 +233,21 @@ fn run() -> Result<(), Error> { #[cfg(target_os = "macos")] { - if !opt.no_system { + if !opt.disable.contains(&Step::System) { report.push_result(execute(|| macos::upgrade_macos(run_type), opt.no_retry)?); } } #[cfg(target_os = "freebsd")] { - if !opt.no_system { + if !opt.disable.contains(&Step::System) { report.push_result(execute(|| freebsd::upgrade_freebsd(&sudo, run_type), opt.no_retry)?); } } #[cfg(windows)] { - if !opt.no_system { + if !opt.disable.contains(&Step::System) { report.push_result(execute(|| powershell.windows_update(run_type), opt.no_retry)?); } }