feat(core): improve migration exit code handling
This commit is contained in:
		
							parent
							
								
									5a4f0dee31
								
							
						
					
					
						commit
						f984d22f0c
					
				|  | @ -17,9 +17,9 @@ | ||||||
|  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
 |  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| use std::path::PathBuf; | use std::{path::PathBuf, sync::Mutex}; | ||||||
| 
 | 
 | ||||||
| use crate::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::*; | ||||||
|  | @ -27,6 +27,10 @@ use dialoguer::Confirm; | ||||||
| use fs_extra::dir::CopyOptions; | use fs_extra::dir::CopyOptions; | ||||||
| use tempdir::TempDir; | use tempdir::TempDir; | ||||||
| 
 | 
 | ||||||
|  | lazy_static! { | ||||||
|  |   static ref CURRENT_PANIC_EXIT_CODE: Mutex<i32> = Mutex::new(MIGRATE_UNEXPECTED_FAILURE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn new() -> CliModule { | pub fn new() -> CliModule { | ||||||
|   CliModule { |   CliModule { | ||||||
|     requires_paths: true, |     requires_paths: true, | ||||||
|  | @ -39,19 +43,22 @@ pub fn new() -> CliModule { | ||||||
| 
 | 
 | ||||||
| fn migrate_main(args: CliModuleArgs) -> i32 { | 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"); | ||||||
|  | 
 | ||||||
|  |   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"); |     eprintln!("Can't migrate configurations, as the default directory [1] is already encoded with the new format"); | ||||||
|     eprintln!("[1]: {:?}", paths.config); |     eprintln!("[1]: {:?}", paths.config); | ||||||
|     eprintln!("The migration tool is only meant to convert the espanso's legacy configuration format (prior to"); |     eprintln!("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)"); |     eprintln!("version 0.7.3) to the new one (since version 2.0)"); | ||||||
|     return 1; |     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"); |     eprintln!("An instance of legacy espanso is running, please terminate it, otherwise the migration can't be performed"); | ||||||
|     return 2; |     return MIGRATE_LEGACY_INSTANCE_RUNNING; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   let target_backup_dir = find_available_backup_dir(); |   let target_backup_dir = find_available_backup_dir(); | ||||||
|  | @ -73,16 +80,19 @@ fn migrate_main(args: CliModuleArgs) -> i32 { | ||||||
|   println!("   the current content of the config directory."); |   println!("   the current content of the config directory."); | ||||||
|   println!(""); |   println!(""); | ||||||
| 
 | 
 | ||||||
|   if !Confirm::new() |   if !cli_args.is_present("noconfirm") { | ||||||
|     .with_prompt("Do you want to proceed?") |     if !Confirm::new() | ||||||
|     .default(true) |       .with_prompt("Do you want to proceed?") | ||||||
|     .interact() |       .default(true) | ||||||
|     .expect("unable to read choice") |       .interact() | ||||||
|   { |       .expect("unable to read choice") | ||||||
|     return 2; |     { | ||||||
|  |       return MIGRATE_USER_ABORTED; | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   println!("Backing up your configuration..."); |   println!("Backing up your configuration..."); | ||||||
|  |   update_panic_exit_code(MIGRATE_CLEAN_FAILURE); | ||||||
| 
 | 
 | ||||||
|   fs_extra::dir::copy( |   fs_extra::dir::copy( | ||||||
|     &paths.config, |     &paths.config, | ||||||
|  | @ -103,9 +113,11 @@ fn migrate_main(args: CliModuleArgs) -> i32 { | ||||||
|   println!("{}", "Conversion completed!".green()); |   println!("{}", "Conversion completed!".green()); | ||||||
| 
 | 
 | ||||||
|   println!("Replacing old configuration with the new one..."); |   println!("Replacing old configuration with the new one..."); | ||||||
|  |   update_panic_exit_code(MIGRATE_DIRTY_FAILURE); | ||||||
| 
 | 
 | ||||||
|   let mut to_be_removed = Vec::new(); |   let mut to_be_removed = Vec::new(); | ||||||
|   let legacy_dir_content = fs_extra::dir::get_dir_content(&paths.config).expect("unable to list legacy dir files"); |   let legacy_dir_content = | ||||||
|  |     fs_extra::dir::get_dir_content(&paths.config).expect("unable to list legacy dir files"); | ||||||
|   to_be_removed.extend(legacy_dir_content.files); |   to_be_removed.extend(legacy_dir_content.files); | ||||||
|   to_be_removed.extend(legacy_dir_content.directories); |   to_be_removed.extend(legacy_dir_content.directories); | ||||||
|   fs_extra::remove_items(&to_be_removed).expect("unable to remove previous configuration"); |   fs_extra::remove_items(&to_be_removed).expect("unable to remove previous configuration"); | ||||||
|  | @ -126,7 +138,7 @@ fn migrate_main(args: CliModuleArgs) -> i32 { | ||||||
| 
 | 
 | ||||||
|   println!("{}", "Configuration successfully migrated!".green()); |   println!("{}", "Configuration successfully migrated!".green()); | ||||||
| 
 | 
 | ||||||
|   0 |   MIGRATE_SUCCESS | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn find_available_backup_dir() -> PathBuf { | fn find_available_backup_dir() -> PathBuf { | ||||||
|  | @ -148,3 +160,18 @@ fn find_available_backup_dir() -> PathBuf { | ||||||
| 
 | 
 | ||||||
|   panic!("could not generate valid backup directory"); |   panic!("could not generate valid backup directory"); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | fn configure_custom_panic_hook() { | ||||||
|  |   let previous_hook = std::panic::take_hook(); | ||||||
|  |   std::panic::set_hook(Box::new(move |info| { | ||||||
|  |     (*previous_hook)(info); | ||||||
|  | 
 | ||||||
|  |     let exit_code = CURRENT_PANIC_EXIT_CODE.lock().unwrap(); | ||||||
|  |     std::process::exit(*exit_code); | ||||||
|  |   })); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn update_panic_exit_code(exit_code: i32) { | ||||||
|  |   let mut lock = CURRENT_PANIC_EXIT_CODE.lock().expect("unable to update panic exit code"); | ||||||
|  |   *lock = exit_code; | ||||||
|  | } | ||||||
|  | @ -28,3 +28,11 @@ pub const DAEMON_SUCCESS: i32 = 0; | ||||||
| pub const DAEMON_ALREADY_RUNNING: i32 = 1; | pub const DAEMON_ALREADY_RUNNING: i32 = 1; | ||||||
| pub const DAEMON_GENERAL_ERROR: i32 = 2; | pub const DAEMON_GENERAL_ERROR: i32 = 2; | ||||||
| pub const DAEMON_LEGACY_ALREADY_RUNNING: i32 = 3; | pub const DAEMON_LEGACY_ALREADY_RUNNING: i32 = 3; | ||||||
|  | 
 | ||||||
|  | pub const MIGRATE_SUCCESS: i32 = 0; | ||||||
|  | pub const MIGRATE_ALREADY_NEW_FORMAT: i32 = 1; | ||||||
|  | pub const MIGRATE_LEGACY_INSTANCE_RUNNING: i32 = 2; | ||||||
|  | pub const MIGRATE_USER_ABORTED: i32 = 3; | ||||||
|  | pub const MIGRATE_CLEAN_FAILURE: i32 = 50; | ||||||
|  | pub const MIGRATE_DIRTY_FAILURE: i32 = 51; | ||||||
|  | pub const MIGRATE_UNEXPECTED_FAILURE: i32 = 101; | ||||||
|  | @ -223,7 +223,10 @@ 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") | ||||||
|  |           .long("noconfirm")) | ||||||
|  |           .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")
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user