Add a command for editing the configuration
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use super::error::{Error, ErrorKind};
|
use super::error::{Error, ErrorKind};
|
||||||
|
use super::utils::editor;
|
||||||
use directories::BaseDirs;
|
use directories::BaseDirs;
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@@ -8,6 +9,8 @@ use serde::Deserialize;
|
|||||||
use shellexpand;
|
use shellexpand;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::{BTreeMap, HashMap};
|
||||||
use std::fs::write;
|
use std::fs::write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
use toml;
|
use toml;
|
||||||
@@ -87,10 +90,7 @@ pub struct ConfigFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigFile {
|
impl ConfigFile {
|
||||||
/// Read the configuration file.
|
fn ensure(base_dirs: &BaseDirs) -> Result<PathBuf, Error> {
|
||||||
///
|
|
||||||
/// If the configuration file does not exist the function returns the default ConfigFile.
|
|
||||||
fn read(base_dirs: &BaseDirs) -> Result<ConfigFile, Error> {
|
|
||||||
let config_path = base_dirs.config_dir().join("topgrade.toml");
|
let config_path = base_dirs.config_dir().join("topgrade.toml");
|
||||||
if !config_path.exists() {
|
if !config_path.exists() {
|
||||||
write(&config_path, include_str!("../config.example.toml"))
|
write(&config_path, include_str!("../config.example.toml"))
|
||||||
@@ -100,12 +100,20 @@ impl ConfigFile {
|
|||||||
config_path.display(),
|
config_path.display(),
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
|
e
|
||||||
})
|
})
|
||||||
.ok();
|
.context(ErrorKind::Configuration)?;
|
||||||
debug!("No configuration exists");
|
debug!("No configuration exists");
|
||||||
return Ok(Default::default());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(config_path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the configuration file.
|
||||||
|
///
|
||||||
|
/// If the configuration file does not exist the function returns the default ConfigFile.
|
||||||
|
fn read(base_dirs: &BaseDirs) -> Result<ConfigFile, Error> {
|
||||||
|
let config_path = Self::ensure(base_dirs)?;
|
||||||
let mut result: Self = toml::from_str(&fs::read_to_string(config_path).context(ErrorKind::Configuration)?)
|
let mut result: Self = toml::from_str(&fs::read_to_string(config_path).context(ErrorKind::Configuration)?)
|
||||||
.context(ErrorKind::Configuration)?;
|
.context(ErrorKind::Configuration)?;
|
||||||
|
|
||||||
@@ -119,12 +127,29 @@ impl ConfigFile {
|
|||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn edit(base_dirs: &BaseDirs) -> Result<(), Error> {
|
||||||
|
let config_path = Self::ensure(base_dirs)?;
|
||||||
|
let editor = editor();
|
||||||
|
|
||||||
|
debug!("Editing {} with {}", config_path.display(), editor);
|
||||||
|
Command::new(editor)
|
||||||
|
.arg(config_path)
|
||||||
|
.spawn()
|
||||||
|
.and_then(|mut p| p.wait())
|
||||||
|
.context(ErrorKind::Configuration)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(StructOpt, Debug)]
|
#[derive(StructOpt, Debug)]
|
||||||
#[structopt(name = "Topgrade")]
|
#[structopt(name = "Topgrade", raw(setting = "structopt::clap::AppSettings::ColoredHelp"))]
|
||||||
/// Command line arguments
|
/// Command line arguments
|
||||||
pub struct CommandLineArgs {
|
pub struct CommandLineArgs {
|
||||||
|
/// Edit the configuration file
|
||||||
|
#[structopt(long = "edit-config")]
|
||||||
|
edit_config: bool,
|
||||||
|
|
||||||
/// Run inside tmux
|
/// Run inside tmux
|
||||||
#[structopt(short = "t", long = "tmux")]
|
#[structopt(short = "t", long = "tmux")]
|
||||||
run_in_tmux: bool,
|
run_in_tmux: bool,
|
||||||
@@ -185,6 +210,11 @@ impl Config {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Launch an editor to edit the configuration
|
||||||
|
pub fn edit(base_dirs: &BaseDirs) -> Result<(), Error> {
|
||||||
|
ConfigFile::edit(base_dirs)
|
||||||
|
}
|
||||||
|
|
||||||
/// The list of commands to run before performing any step.
|
/// The list of commands to run before performing any step.
|
||||||
pub fn pre_commands(&self) -> &Option<Commands> {
|
pub fn pre_commands(&self) -> &Option<Commands> {
|
||||||
&self.config_file.pre_commands
|
&self.config_file.pre_commands
|
||||||
@@ -244,4 +274,9 @@ impl Config {
|
|||||||
pub fn keep_at_end(&self) -> bool {
|
pub fn keep_at_end(&self) -> bool {
|
||||||
self.opt.keep_at_end || env::var("TOPGRADE_KEEP_END").is_ok()
|
self.opt.keep_at_end || env::var("TOPGRADE_KEEP_END").is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether to edit the configuration file
|
||||||
|
pub fn edit_config(&self) -> bool {
|
||||||
|
self.opt.edit_config
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ fn run() -> Result<(), Error> {
|
|||||||
let base_dirs = directories::BaseDirs::new().ok_or(ErrorKind::NoBaseDirectories)?;
|
let base_dirs = directories::BaseDirs::new().ok_or(ErrorKind::NoBaseDirectories)?;
|
||||||
let config = Config::load(&base_dirs)?;
|
let config = Config::load(&base_dirs)?;
|
||||||
|
|
||||||
|
if config.edit_config() {
|
||||||
|
Config::edit(&base_dirs)?;
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
if config.run_in_tmux() && env::var("TOPGRADE_INSIDE_TMUX").is_err() {
|
if config.run_in_tmux() && env::var("TOPGRADE_INSIDE_TMUX").is_err() {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use super::error::{Error, ErrorKind};
|
use super::error::{Error, ErrorKind};
|
||||||
use log::{debug, error};
|
use log::{debug, error};
|
||||||
|
use std::env;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
@@ -138,6 +139,10 @@ impl<'a> fmt::Display for HumanizedPath<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn editor() -> String {
|
||||||
|
env::var("EDITOR").unwrap_or_else(|_| String::from(if cfg!(windows) { "notepad" } else { "vi" }))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user