diff --git a/README.md b/README.md index a1928af4..54d63501 100644 --- a/README.md +++ b/README.md @@ -113,29 +113,7 @@ Just run `topgrade`. It will run the following steps: * **FreeBSD**: Run `freebsd-upgrade` ## Customization -Here's an example for a configuration file: - - -``` toml -git_repos = [ - "~/src/*/", - "~/.config/something" -] - -# Same options as the command line flag -disable = ["system", "emacs"] - -[pre_commands] -"Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" - -[commands] -"Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter" -``` -* `git_repos` - A list of custom Git repositories to pull -* `pre_commands` - Commands to execute before starting any action. If any command fails, Topgrade - will not proceed -* `commands` - Custom upgrade steps. If any command fails it will be reported in the summary as all - upgrade steps are reported, but it will not cause Topgrade to stop. +See `config.example.toml` for an example configuration file. ### Configuration path diff --git a/config.example.toml b/config.example.toml new file mode 100644 index 00000000..2319bfb9 --- /dev/null +++ b/config.example.toml @@ -0,0 +1,19 @@ +# Additional git repositories to pull +#git_repos = [ +# "~/src/*/", +# "~/.config/something" +#] + +# Same options as the command line flag +#disable = ["system", "emacs"] + +# List of remote machines with Topgrade installed on them +#remote_topgrades = ["toothless", "pi", "parnas"] + +# Commands to run before anything +#[pre_commands] +#"Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak" + +# Custom commands +#[commands] +#"Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter" diff --git a/src/config.rs b/src/config.rs index cc32007e..1cf0d5c6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,9 +2,12 @@ use super::error::{Error, ErrorKind}; use directories::BaseDirs; use failure::ResultExt; use lazy_static::lazy_static; +use log::{debug, error, LevelFilter}; +use pretty_env_logger::formatted_timed_builder; use serde::Deserialize; use shellexpand; use std::collections::{BTreeMap, HashMap}; +use std::fs::write; use std::{env, fs}; use structopt::StructOpt; use toml; @@ -72,7 +75,7 @@ impl std::str::FromStr for Step { } } -#[derive(Deserialize, Default)] +#[derive(Deserialize, Default, Debug)] #[serde(deny_unknown_fields)] /// Configuration file pub struct ConfigFile { @@ -90,6 +93,16 @@ impl ConfigFile { fn read(base_dirs: &BaseDirs) -> Result { let config_path = base_dirs.config_dir().join("topgrade.toml"); if !config_path.exists() { + write(&config_path, include_str!("../config.example.toml")) + .map_err(|e| { + error!( + "Unable to write the example configuration file to {}: {}", + config_path.display(), + e + ); + }) + .ok(); + debug!("No configuration exists"); return Ok(Default::default()); } @@ -102,6 +115,8 @@ impl ConfigFile { } } + debug!("Loaded configuration: {:?}", result); + Ok(result) } } @@ -154,8 +169,18 @@ impl Config { /// /// The function parses the command line arguments and reading the configuration file. pub fn load(base_dirs: &BaseDirs) -> Result { + let opt = CommandLineArgs::from_args(); + + let mut builder = formatted_timed_builder(); + + if opt.verbose { + builder.filter(Some("topgrade"), LevelFilter::Trace); + } + + builder.init(); + Ok(Self { - opt: CommandLineArgs::from_args(), + opt, config_file: ConfigFile::read(base_dirs)?, }) } @@ -210,11 +235,6 @@ impl Config { self.opt.no_retry } - /// Tell whether we should print log. - pub fn verbose(&self) -> bool { - self.opt.verbose - } - /// List of remote hosts to run Topgrade in pub fn remote_topgrades(&self) -> &Option> { &self.config_file.remote_topgrades diff --git a/src/main.rs b/src/main.rs index b7e7165d..e47c51ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,10 +16,9 @@ use self::report::Report; use self::steps::*; use self::terminal::*; use failure::{Fail, ResultExt}; -use log::{debug, LevelFilter}; +use log::debug; #[cfg(feature = "self-update")] use openssl_probe; -use pretty_env_logger::formatted_timed_builder; use std::borrow::Cow; use std::env; use std::fmt::Debug; @@ -75,14 +74,6 @@ fn run() -> Result<(), Error> { } } - let mut builder = formatted_timed_builder(); - - if config.verbose() { - builder.filter(Some("topgrade"), LevelFilter::Trace); - } - - builder.init(); - let git = git::Git::new(); let mut git_repos = git::Repositories::new(&git);