feat(core): improve migration error logging

This commit is contained in:
Federico Terzi 2021-06-15 23:15:43 +02:00
parent f984d22f0c
commit b47279db63
3 changed files with 86 additions and 17 deletions

View File

@ -19,12 +19,20 @@
use std::{path::PathBuf, sync::Mutex}; use std::{path::PathBuf, sync::Mutex};
use crate::{exit_code::{MIGRATE_ALREADY_NEW_FORMAT, MIGRATE_CLEAN_FAILURE, MIGRATE_DIRTY_FAILURE, MIGRATE_LEGACY_INSTANCE_RUNNING, MIGRATE_SUCCESS, MIGRATE_UNEXPECTED_FAILURE, MIGRATE_USER_ABORTED}, lock::acquire_legacy_lock}; use crate::{
exit_code::{
MIGRATE_ALREADY_NEW_FORMAT, MIGRATE_CLEAN_FAILURE, MIGRATE_DIRTY_FAILURE,
MIGRATE_LEGACY_INSTANCE_RUNNING, MIGRATE_SUCCESS, MIGRATE_UNEXPECTED_FAILURE,
MIGRATE_USER_ABORTED,
},
lock::acquire_legacy_lock,
};
use super::{CliModule, CliModuleArgs}; use super::{CliModule, CliModuleArgs};
use colored::*; use colored::*;
use dialoguer::Confirm; use dialoguer::Confirm;
use fs_extra::dir::CopyOptions; use fs_extra::dir::CopyOptions;
use log::{error, info};
use tempdir::TempDir; use tempdir::TempDir;
lazy_static! { lazy_static! {
@ -33,8 +41,11 @@ lazy_static! {
pub fn new() -> CliModule { pub fn new() -> CliModule {
CliModule { CliModule {
enable_logs: true,
disable_logs_terminal_output: true,
requires_paths: true, requires_paths: true,
requires_config: true, requires_config: true,
log_mode: super::LogMode::AppendOnly,
subcommand: "migrate".to_string(), subcommand: "migrate".to_string(),
entry: migrate_main, entry: migrate_main,
..Default::default() ..Default::default()
@ -45,19 +56,21 @@ fn migrate_main(args: CliModuleArgs) -> i32 {
let paths = args.paths.expect("missing paths argument"); let paths = args.paths.expect("missing paths argument");
let cli_args = args.cli_args.expect("missing cli_args"); let cli_args = args.cli_args.expect("missing cli_args");
info!("--- MIGRATION STARTED ---");
configure_custom_panic_hook(); configure_custom_panic_hook();
if !args.is_legacy_config { if !args.is_legacy_config {
eprintln!("Can't migrate configurations, as the default directory [1] is already encoded with the new format"); error_print_and_log("Can't migrate configurations, as the default directory [1] is already encoded with the new format");
eprintln!("[1]: {:?}", paths.config); error_print_and_log(&format!("[1]: {:?}", paths.config));
eprintln!("The migration tool is only meant to convert the espanso's legacy configuration format (prior to"); error_print_and_log("The migration tool is only meant to convert the espanso's legacy configuration format (prior to");
eprintln!("version 0.7.3) to the new one (since version 2.0)"); error_print_and_log("version 0.7.3) to the new one (since version 2.0)");
return MIGRATE_ALREADY_NEW_FORMAT; return MIGRATE_ALREADY_NEW_FORMAT;
} }
let legacy_lock_file = acquire_legacy_lock(&paths.runtime); let legacy_lock_file = acquire_legacy_lock(&paths.runtime);
if legacy_lock_file.is_none() { if legacy_lock_file.is_none() {
eprintln!("An instance of legacy espanso is running, please terminate it, otherwise the migration can't be performed"); error_print_and_log("An instance of legacy espanso is running, please terminate it, otherwise the migration can't be performed");
return MIGRATE_LEGACY_INSTANCE_RUNNING; return MIGRATE_LEGACY_INSTANCE_RUNNING;
} }
@ -80,6 +93,15 @@ fn migrate_main(args: CliModuleArgs) -> i32 {
println!(" the current content of the config directory."); println!(" the current content of the config directory.");
println!(""); println!("");
info!(
"backing up the configuration directory: '{}'",
paths.config.to_string_lossy()
);
info!(
" -> into this folder: '{}'",
target_backup_dir.to_string_lossy()
);
if !cli_args.is_present("noconfirm") { if !cli_args.is_present("noconfirm") {
if !Confirm::new() if !Confirm::new()
.with_prompt("Do you want to proceed?") .with_prompt("Do you want to proceed?")
@ -104,15 +126,19 @@ fn migrate_main(args: CliModuleArgs) -> i32 {
) )
.expect("unable to backup the current config"); .expect("unable to backup the current config");
println!("{}", "Backup completed!".green()); println!("{}", "Backup completed!".green());
info!("backup completed!");
println!("Converting the configuration..."); println!("Converting the configuration...");
info!("converting the configuration...");
let temp_dir = TempDir::new("espanso-migrate-out").expect("unable to create temporary directory"); let temp_dir = TempDir::new("espanso-migrate-out").expect("unable to create temporary directory");
let temp_out_dir = temp_dir.path().join("out"); let temp_out_dir = temp_dir.path().join("out");
espanso_migrate::migrate(&paths.config, &paths.packages, &temp_out_dir) espanso_migrate::migrate(&paths.config, &paths.packages, &temp_out_dir)
.expect("an error occurred while converting the configuration"); .expect("an error occurred while converting the configuration");
println!("{}", "Conversion completed!".green()); println!("{}", "Conversion completed!".green());
info!("conversion completed!");
println!("Replacing old configuration with the new one..."); println!("Replacing old configuration with the new one...");
info!("replacing old configuration with the new one...");
update_panic_exit_code(MIGRATE_DIRTY_FAILURE); update_panic_exit_code(MIGRATE_DIRTY_FAILURE);
let mut to_be_removed = Vec::new(); let mut to_be_removed = Vec::new();
@ -137,6 +163,7 @@ fn migrate_main(args: CliModuleArgs) -> i32 {
} }
println!("{}", "Configuration successfully migrated!".green()); println!("{}", "Configuration successfully migrated!".green());
info!("configuration migrated!");
MIGRATE_SUCCESS MIGRATE_SUCCESS
} }
@ -166,12 +193,44 @@ fn configure_custom_panic_hook() {
std::panic::set_hook(Box::new(move |info| { std::panic::set_hook(Box::new(move |info| {
(*previous_hook)(info); (*previous_hook)(info);
// Part of this code is taken from the "rust-log-panics" crate
let thread = std::thread::current();
let thread = thread.name().unwrap_or("<unnamed>");
let msg = match info.payload().downcast_ref::<&'static str>() {
Some(s) => *s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => &**s,
None => "Box<Any>",
},
};
match info.location() {
Some(location) => {
eprintln!(
"ERROR: '{}' panicked at '{}': {}:{}",
thread,
msg,
location.file(),
location.line(),
);
}
None => eprintln!("ERROR: '{}' panicked at '{}'", thread, msg,),
}
let exit_code = CURRENT_PANIC_EXIT_CODE.lock().unwrap(); let exit_code = CURRENT_PANIC_EXIT_CODE.lock().unwrap();
std::process::exit(*exit_code); std::process::exit(*exit_code);
})); }));
} }
fn update_panic_exit_code(exit_code: i32) { fn update_panic_exit_code(exit_code: i32) {
let mut lock = CURRENT_PANIC_EXIT_CODE.lock().expect("unable to update panic exit code"); let mut lock = CURRENT_PANIC_EXIT_CODE
.lock()
.expect("unable to update panic exit code");
*lock = exit_code; *lock = exit_code;
} }
fn error_print_and_log(msg: &str) {
error!("{}", msg);
eprintln!("{}", msg);
}

View File

@ -31,6 +31,7 @@ pub mod worker;
pub struct CliModule { pub struct CliModule {
pub enable_logs: bool, pub enable_logs: bool,
pub disable_logs_terminal_output: bool,
pub log_mode: LogMode, pub log_mode: LogMode,
pub requires_paths: bool, pub requires_paths: bool,
pub requires_config: bool, pub requires_config: bool,
@ -43,6 +44,7 @@ impl Default for CliModule {
Self { Self {
enable_logs: false, enable_logs: false,
log_mode: LogMode::Read, log_mode: LogMode::Read,
disable_logs_terminal_output: false,
requires_paths: false, requires_paths: false,
requires_config: false, requires_config: false,
subcommand: "".to_string(), subcommand: "".to_string(),

View File

@ -30,7 +30,7 @@ use cli::{CliModule, CliModuleArgs};
use log::{error, info, warn}; use log::{error, info, warn};
use logging::FileProxy; use logging::FileProxy;
use simplelog::{ use simplelog::{
CombinedLogger, ConfigBuilder, LevelFilter, TermLogger, TerminalMode, WriteLogger, CombinedLogger, ConfigBuilder, LevelFilter, SharedLogger, TermLogger, TerminalMode, WriteLogger,
}; };
use crate::cli::LogMode; use crate::cli::LogMode;
@ -224,9 +224,8 @@ fn main() {
.subcommand( .subcommand(
SubCommand::with_name("migrate") SubCommand::with_name("migrate")
.about("Automatically migrate legacy config files to the new v2 format.") .about("Automatically migrate legacy config files to the new v2 format.")
.arg(Arg::with_name("noconfirm") .arg(Arg::with_name("noconfirm").long("noconfirm"))
.long("noconfirm")) .help("Migrate the configuration without asking for confirmation"),
.help("Migrate the configuration without asking for confirmation"),
) )
// .subcommand(SubCommand::with_name("match") // .subcommand(SubCommand::with_name("match")
// .about("List and execute matches from the CLI") // .about("List and execute matches from the CLI")
@ -319,11 +318,20 @@ fn main() {
.add_filter_ignore_str("html5ever") .add_filter_ignore_str("html5ever")
.build(); .build();
CombinedLogger::init(vec![ let mut outputs: Vec<Box<dyn SharedLogger>> = vec![WriteLogger::new(
TermLogger::new(log_level, config.clone(), TerminalMode::Mixed), LevelFilter::Info,
WriteLogger::new(LevelFilter::Info, config, log_proxy.clone()), config.clone(),
]) log_proxy.clone(),
.expect("unable to initialize logs"); )];
if !handler.disable_logs_terminal_output {
outputs.insert(
0,
TermLogger::new(log_level, config.clone(), TerminalMode::Mixed),
);
}
CombinedLogger::init(outputs).expect("unable to initialize logs");
// Activate logging for panics // Activate logging for panics
log_panics::init(); log_panics::init();