From e992fe4f0c715976b7e10d043947d2a280424241 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Tue, 15 Jun 2021 23:29:04 +0200 Subject: [PATCH] feat(core): implement wizard migration handler --- espanso/src/cli/launcher/mod.rs | 47 +++++++++++++++++++------- espanso/src/cli/launcher/util.rs | 57 +++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 17 deletions(-) diff --git a/espanso/src/cli/launcher/mod.rs b/espanso/src/cli/launcher/mod.rs index 8857bf6..61e983b 100644 --- a/espanso/src/cli/launcher/mod.rs +++ b/espanso/src/cli/launcher/mod.rs @@ -17,7 +17,9 @@ * along with espanso. If not, see . */ -use espanso_modulo::wizard::{WizardHandlers, WizardOptions}; +use espanso_modulo::wizard::{MigrationResult, WizardHandlers, WizardOptions}; + +use self::util::MigrationError; use super::{CliModule, CliModuleArgs}; @@ -29,6 +31,7 @@ pub fn new() -> CliModule { #[allow(clippy::needless_update)] CliModule { requires_paths: true, + requires_config: true, enable_logs: false, subcommand: "launcher".to_string(), entry: launcher_main, @@ -39,25 +42,45 @@ pub fn new() -> CliModule { #[cfg(feature = "modulo")] fn launcher_main(args: CliModuleArgs) -> i32 { let paths = args.paths.expect("missing paths in launcher main"); - let cli_args = args.cli_args.expect("missing cli_args in launcher main"); let icon_paths = crate::icon::load_icon_paths(&paths.runtime).expect("unable to load icon paths"); // TODO: should move wizard to "init" subcommand? let is_legacy_version_page_enabled = util::is_legacy_version_running(&paths.runtime); let runtime_dir_clone = paths.runtime.clone(); - let is_legacy_version_running_handler = Box::new(move || { - util::is_legacy_version_running(&runtime_dir_clone) - }); + let is_legacy_version_running_handler = + Box::new(move || util::is_legacy_version_running(&runtime_dir_clone)); + + let is_migrate_page_enabled = args.is_legacy_config; + let paths_clone = paths.clone(); + let backup_and_migrate_handler = + Box::new(move || match util::migrate_configuration(&paths_clone) { + Ok(_) => { + MigrationResult::Success + } + Err(error) => { + match error.downcast_ref::() { + Some(MigrationError::DirtyError) => { + MigrationResult::DirtyFailure + } + Some(MigrationError::CleanError) => { + MigrationResult::CleanFailure + } + _ => { + MigrationResult::UnknownFailure + } + } + } + }); espanso_modulo::wizard::show(WizardOptions { version: crate::VERSION.to_string(), - is_welcome_page_enabled: true, // TODO - is_move_bundle_page_enabled: false, // TODO + is_welcome_page_enabled: true, // TODO + is_move_bundle_page_enabled: false, // TODO is_legacy_version_page_enabled, - is_migrate_page_enabled: true, // TODO, - is_add_path_page_enabled: true, // TODO - is_accessibility_page_enabled: true, // TODO + is_migrate_page_enabled, + is_add_path_page_enabled: true, // TODO + is_accessibility_page_enabled: true, // TODO window_icon_path: icon_paths .wizard_icon .map(|path| path.to_string_lossy().to_string()), @@ -68,7 +91,7 @@ fn launcher_main(args: CliModuleArgs) -> i32 { accessibility_image_2_path: None, handlers: WizardHandlers { is_legacy_version_running: Some(is_legacy_version_running_handler), - backup_and_migrate: None, + backup_and_migrate: Some(backup_and_migrate_handler), add_to_path: None, enable_accessibility: None, is_accessibility_enabled: None, @@ -83,4 +106,4 @@ fn launcher_main(args: CliModuleArgs) -> i32 { #[cfg(not(feature = "modulo"))] fn launcher_main(_: CliModuleArgs) -> i32 { // TODO: handle what happens here -} \ No newline at end of file +} diff --git a/espanso/src/cli/launcher/util.rs b/espanso/src/cli/launcher/util.rs index c842fd1..b792417 100644 --- a/espanso/src/cli/launcher/util.rs +++ b/espanso/src/cli/launcher/util.rs @@ -17,15 +17,62 @@ * along with espanso. If not, see . */ -use std::path::Path; +use std::{path::Path, process::Command}; -use crate::lock::acquire_legacy_lock; +use anyhow::Result; +use thiserror::Error; +use espanso_path::Paths; + +use crate::{exit_code::{MIGRATE_CLEAN_FAILURE, MIGRATE_DIRTY_FAILURE}, lock::acquire_legacy_lock}; pub fn is_legacy_version_running(runtime_path: &Path) -> bool { let legacy_lock_file = acquire_legacy_lock(runtime_path); if legacy_lock_file.is_none() { - true + true } else { - false + false } -} \ No newline at end of file +} + +pub fn migrate_configuration(paths: &Paths) -> Result<()> { + let espanso_exe_path = std::env::current_exe()?; + let mut command = Command::new(&espanso_exe_path.to_string_lossy().to_string()); + command.args(&["migrate", "--noconfirm"]); + command.env( + "ESPANSO_CONFIG_DIR", + paths.config.to_string_lossy().to_string(), + ); + command.env( + "ESPANSO_PACKAGE_DIR", + paths.packages.to_string_lossy().to_string(), + ); + command.env( + "ESPANSO_RUNTIME_DIR", + paths.runtime.to_string_lossy().to_string(), + ); + + let mut child = command.spawn()?; + let result = child.wait()?; + + if result.success() { + Ok(()) + } else { + match result.code() { + Some(code) if code == MIGRATE_CLEAN_FAILURE => Err(MigrationError::CleanError.into()), + Some(code) if code == MIGRATE_DIRTY_FAILURE=> Err(MigrationError::DirtyError.into()), + _ => Err(MigrationError::UnexpectedError.into()) + } + } +} + +#[derive(Error, Debug)] +pub enum MigrationError { + #[error("clean error")] + CleanError, + + #[error("dirty error")] + DirtyError, + + #[error("unexpected error")] + UnexpectedError, +}