Allow most command-line options to be configured in config file… (#237)

This commit is contained in:
Idan Katz
2019-10-10 11:26:00 +03:00
committed by Roey Darwish Dror
parent 6bed2f66c5
commit 43f0b75397
2 changed files with 53 additions and 18 deletions

View File

@@ -4,9 +4,18 @@
# "~/.config/something" # "~/.config/something"
#] #]
# Same options as the command line flag # Disable specific steps - same options as the command line flag
#disable = ["system", "emacs"] #disable = ["system", "emacs"]
# Run specific steps - same options as the command line flag
#only = ["system", "emacs"]
# Do not ask to retry failed steps (default: false)
#no_retry = true
# Run inside tmux
#run_in_tmux = true
# List of remote machines with Topgrade installed on them # List of remote machines with Topgrade installed on them
#remote_topgrades = ["toothless", "pi", "parnas"] #remote_topgrades = ["toothless", "pi", "parnas"]
@@ -28,3 +37,9 @@
# Custom commands # Custom commands
#[commands] #[commands]
#"Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter" #"Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter"
# Output logs
#verbose = true
# Cleanup temporary or old files
#cleanup = true

View File

@@ -2,7 +2,7 @@ use super::error::{Error, ErrorKind};
use super::utils::editor; use super::utils::editor;
use directories::BaseDirs; use directories::BaseDirs;
use failure::ResultExt; use failure::ResultExt;
use strum::{EnumString, EnumVariantNames}; use strum::{EnumIter, EnumString, EnumVariantNames, IntoEnumIterator};
use log::{debug, error, LevelFilter}; use log::{debug, error, LevelFilter};
use pretty_env_logger::formatted_timed_builder; use pretty_env_logger::formatted_timed_builder;
@@ -18,7 +18,7 @@ use toml;
type Commands = BTreeMap<String, String>; type Commands = BTreeMap<String, String>;
#[derive(EnumString, EnumVariantNames, Debug, Clone, PartialEq, Deserialize)] #[derive(EnumString, EnumVariantNames, Debug, Clone, PartialEq, Deserialize, EnumIter)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[strum(serialize_all = "snake_case")] #[strum(serialize_all = "snake_case")]
pub enum Step { pub enum Step {
@@ -62,6 +62,11 @@ pub struct ConfigFile {
set_title: Option<bool>, set_title: Option<bool>,
assume_yes: Option<bool>, assume_yes: Option<bool>,
yay_arguments: Option<String>, yay_arguments: Option<String>,
no_retry: Option<bool>,
run_in_tmux: Option<bool>,
verbose: Option<bool>,
cleanup: Option<bool>,
only: Option<Vec<Step>>,
} }
impl ConfigFile { impl ConfigFile {
@@ -170,6 +175,7 @@ pub struct CommandLineArgs {
pub struct Config { pub struct Config {
opt: CommandLineArgs, opt: CommandLineArgs,
config_file: ConfigFile, config_file: ConfigFile,
allowed_steps: Vec<Step>,
} }
impl Config { impl Config {
@@ -178,18 +184,22 @@ impl Config {
/// The function parses the command line arguments and reading the configuration file. /// The function parses the command line arguments and reading the configuration file.
pub fn load(base_dirs: &BaseDirs) -> Result<Self, Error> { pub fn load(base_dirs: &BaseDirs) -> Result<Self, Error> {
let opt = CommandLineArgs::from_args(); let opt = CommandLineArgs::from_args();
let config_file = ConfigFile::read(base_dirs)?;
let mut builder = formatted_timed_builder(); let mut builder = formatted_timed_builder();
if opt.verbose { if opt.verbose || config_file.verbose.unwrap_or(false) {
builder.filter(Some("topgrade"), LevelFilter::Trace); builder.filter(Some("topgrade"), LevelFilter::Trace);
} }
let allowed_steps = Self::allowed_steps(&opt, &config_file);
builder.init(); builder.init();
Ok(Self { Ok(Self {
opt, opt,
config_file: ConfigFile::read(base_dirs)?, config_file,
allowed_steps,
}) })
} }
@@ -218,28 +228,38 @@ impl Config {
/// If the step appears either in the `--disable` command line argument /// If the step appears either in the `--disable` command line argument
/// or the `disable` option in the configuration, the function returns false. /// or the `disable` option in the configuration, the function returns false.
pub fn should_run(&self, step: Step) -> bool { pub fn should_run(&self, step: Step) -> bool {
if !self.opt.only.is_empty() { self.allowed_steps.contains(&step)
return self.opt.only.contains(&step);
} }
!(self fn allowed_steps(opt: &CommandLineArgs, config_file: &ConfigFile) -> Vec<Step> {
.config_file let mut enabled_steps: Vec<Step> = if !opt.only.is_empty() {
.disable opt.only.clone()
} else {
config_file
.only
.as_ref() .as_ref()
.map(|d| d.contains(&step)) .map_or_else(|| Step::iter().collect(), |v| v.clone())
.unwrap_or(false) };
|| self.opt.disable.contains(&step))
let disabled_steps: Vec<Step> = if !opt.disable.is_empty() {
opt.disable.clone()
} else {
config_file.disable.as_ref().map_or_else(|| vec![], |v| v.clone())
};
enabled_steps.retain(|e| !disabled_steps.contains(e));
enabled_steps
} }
/// Tell whether we should run in tmux. /// Tell whether we should run in tmux.
pub fn run_in_tmux(&self) -> bool { pub fn run_in_tmux(&self) -> bool {
self.opt.run_in_tmux self.opt.run_in_tmux || self.config_file.run_in_tmux.unwrap_or(false)
} }
/// Tell whether we should perform cleanup steps. /// Tell whether we should perform cleanup steps.
#[cfg(not(windows))] #[cfg(not(windows))]
pub fn cleanup(&self) -> bool { pub fn cleanup(&self) -> bool {
self.opt.cleanup self.opt.cleanup || self.config_file.cleanup.unwrap_or(false)
} }
/// Tell whether we are dry-running. /// Tell whether we are dry-running.
@@ -249,7 +269,7 @@ impl Config {
/// Tell whether we should not attempt to retry anything. /// Tell whether we should not attempt to retry anything.
pub fn no_retry(&self) -> bool { pub fn no_retry(&self) -> bool {
self.opt.no_retry self.opt.no_retry || self.config_file.no_retry.unwrap_or(false)
} }
/// List of remote hosts to run Topgrade in /// List of remote hosts to run Topgrade in