From 45c562d723fbaac511ee6ed20eace4a6eb19a169 Mon Sep 17 00:00:00 2001 From: liushuyu Date: Wed, 27 May 2020 21:36:49 -0600 Subject: [PATCH] meta: add repair functionality --- src/frontend/rest/services/install.rs | 14 +++++-- src/installer.rs | 3 ++ src/tasks/install.rs | 10 +++++ src/tasks/mod.rs | 1 + src/tasks/remove_target_dir.rs | 58 +++++++++++++++++++++++++++ ui/src/locales/en.json | 3 ++ ui/src/views/InstallPackages.vue | 6 +++ ui/src/views/ModifyView.vue | 12 +++++- ui/src/views/SelectPackages.vue | 15 ++++--- 9 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 src/tasks/remove_target_dir.rs diff --git a/src/frontend/rest/services/install.rs b/src/frontend/rest/services/install.rs index f9e1f5c..7265985 100644 --- a/src/frontend/rest/services/install.rs +++ b/src/frontend/rest/services/install.rs @@ -23,11 +23,12 @@ pub fn handle(service: &WebService, req: Request) -> Future { Box::new(req.body().concat2().map(move |b| { let results = form_urlencoded::parse(b.as_ref()) - .into_owned() - .collect::>(); - + .into_owned() + .collect::>(); + let mut to_install = Vec::new(); let mut path: Option = None; + let mut force_install = false; // Transform results into just an array of stuff to install for (key, value) in &results { @@ -36,6 +37,11 @@ pub fn handle(service: &WebService, req: Request) -> Future { continue; } + if key == "mode" && value == "force" { + force_install = true; + continue; + } + if value == "true" { to_install.push(key.to_owned()); } @@ -55,7 +61,7 @@ pub fn handle(service: &WebService, req: Request) -> Future { framework.set_install_dir(&path); } - if let Err(v) = framework.install(to_install, &sender, new_install) { + if let Err(v) = framework.install(to_install, &sender, new_install, force_install) { error!("Install error occurred: {:?}", v); if let Err(v) = sender.send(InstallMessage::Error(v)) { error!("Failed to send install error: {:?}", v); diff --git a/src/installer.rs b/src/installer.rs index 6ba09a3..f6ae763 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -153,11 +153,13 @@ impl InstallerFramework { /// items: Array of named packages to be installed/kept /// messages: Channel used to send progress messages /// fresh_install: If the install directory must be empty + /// force_install: If the install directory should be erased first pub fn install( &mut self, items: Vec, messages: &Sender, fresh_install: bool, + force_install: bool, ) -> Result<(), String> { info!( "Framework: Installing {:?} to {:?}", @@ -186,6 +188,7 @@ impl InstallerFramework { items, uninstall_items, fresh_install, + force_install }); let mut tree = DependencyTree::build(task); diff --git a/src/tasks/install.rs b/src/tasks/install.rs index 0a193d1..d73e413 100644 --- a/src/tasks/install.rs +++ b/src/tasks/install.rs @@ -6,6 +6,7 @@ use crate::tasks::ensure_only_instance::EnsureOnlyInstanceTask; use crate::tasks::install_dir::VerifyInstallDirTask; use crate::tasks::install_global_shortcut::InstallGlobalShortcutsTask; use crate::tasks::install_pkg::InstallPackageTask; +use crate::tasks::remove_target_dir::RemoveTargetDirTask; use crate::tasks::save_executable::SaveExecutableTask; use crate::tasks::uninstall_pkg::UninstallPackageTask; @@ -19,6 +20,8 @@ pub struct InstallTask { pub items: Vec, pub uninstall_items: Vec, pub fresh_install: bool, + // force_install: remove the target directory before installing + pub force_install: bool, } impl Task for InstallTask { @@ -40,6 +43,13 @@ impl Task for InstallTask { Box::new(EnsureOnlyInstanceTask {}), )); + if self.force_install { + elements.push(TaskDependency::build( + TaskOrdering::Pre, + Box::new(RemoveTargetDirTask {}), + )); + } + elements.push(TaskDependency::build( TaskOrdering::Pre, Box::new(VerifyInstallDirTask { diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index 9fa3674..e0f1f41 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -23,6 +23,7 @@ pub mod uninstall; pub mod uninstall_global_shortcut; pub mod uninstall_pkg; pub mod uninstall_shortcuts; +pub mod remove_target_dir; /// An abstraction over the various parameters that can be passed around. pub enum TaskParamType { diff --git a/src/tasks/remove_target_dir.rs b/src/tasks/remove_target_dir.rs new file mode 100644 index 0000000..af27241 --- /dev/null +++ b/src/tasks/remove_target_dir.rs @@ -0,0 +1,58 @@ +//! remove the whole target directory from the existence + +use crate::installer::InstallerFramework; + +use crate::tasks::Task; +use crate::tasks::TaskDependency; +use crate::tasks::TaskMessage; +use crate::tasks::TaskParamType; + +pub struct RemoveTargetDirTask {} + +impl Task for RemoveTargetDirTask { + fn execute( + &mut self, + _: Vec, + context: &mut InstallerFramework, + messenger: &dyn Fn(&TaskMessage), + ) -> Result { + messenger(&TaskMessage::DisplayMessage( + "Removing previous install...", + 0.1, + )); + // erase the database as well + context.database.packages = Vec::new(); + if let Some(path) = context.install_path.as_ref() { + let entries = std::fs::read_dir(path) + .map_err(|e| format!("Error reading {}: {}", path.to_string_lossy(), e))?; + // remove everything except the maintenancetool + for entry in entries { + let path = entry + .map_err(|e| format!("Error reading file: {}", e))? + .path(); + if let Some(filename) = path.file_name() { + if filename.to_string_lossy().starts_with("maintenancetool") { + continue; + } + } + if path.is_dir() { + std::fs::remove_dir_all(&path) + .map_err(|e| format!("Error removing {}: {}", path.to_string_lossy(), e))?; + } else { + std::fs::remove_file(&path) + .map_err(|e| format!("Error removing {}: {}", path.to_string_lossy(), e))?; + } + } + } + + Ok(TaskParamType::None) + } + + fn dependencies(&self) -> Vec { + vec![] + } + + fn name(&self) -> String { + "RemoveTargetDirTask".to_string() + } +} diff --git a/ui/src/locales/en.json b/ui/src/locales/en.json index 3a90532..91c6748 100644 --- a/ui/src/locales/en.json +++ b/ui/src/locales/en.json @@ -13,10 +13,12 @@ }, "select_packages":{ "title":"Select which packages you want to install:", + "title_repair":"Select which packages you want to repair:", "installed":"(installed)", "advanced":"Advanced...", "install":"Install", "modify":"Modify", + "repair": "Repair", "location":"Install Location", "location_placeholder":"Enter a install path here", "select":"Select" @@ -44,6 +46,7 @@ "title":"Choose an option:", "update":"Update", "modify":"Modify", + "repair": "Repair", "uninstall":"Uninstall", "prompt":"Are you sure you want to uninstall {name}?" }, diff --git a/ui/src/views/InstallPackages.vue b/ui/src/views/InstallPackages.vue index 48da345..291ae8a 100644 --- a/ui/src/views/InstallPackages.vue +++ b/ui/src/views/InstallPackages.vue @@ -24,6 +24,7 @@ export default { is_uninstall: false, is_updater_update: false, is_update: false, + is_repair: false, failed_with_error: false, packages_installed: 0 } @@ -32,6 +33,7 @@ export default { this.is_uninstall = this.$route.params.kind === 'uninstall' this.is_updater_update = this.$route.params.kind === 'updater' this.is_update = this.$route.params.kind === 'update' + this.is_repair = this.$route.params.kind === 'repair' console.log('Installer kind: ' + this.$route.params.kind) this.install() }, @@ -51,6 +53,10 @@ export default { results.path = app.install_location + if (this.is_repair) { + results['mode'] = 'force' + } + var targetUrl = '/api/start-install' if (this.is_uninstall) { targetUrl = '/api/uninstall' diff --git a/ui/src/views/ModifyView.vue b/ui/src/views/ModifyView.vue index 8b40f1e..bde1c5f 100644 --- a/ui/src/views/ModifyView.vue +++ b/ui/src/views/ModifyView.vue @@ -14,6 +14,12 @@

+ + {{ $t('modify.repair') }} + +
+
+ {{ $t('modify.uninstall') }} @@ -48,6 +54,9 @@ export default { modify_packages: function () { this.$router.push('/packages') }, + repair_packages: function () { + this.$router.push({ name: 'packages', params: { repair: true } }) + }, prepare_uninstall: function () { this.show_uninstall = true }, @@ -56,7 +65,8 @@ export default { }, uninstall: function () { this.$router.push('/install/uninstall') - } + }, + view_files: function () {} } } diff --git a/ui/src/views/SelectPackages.vue b/ui/src/views/SelectPackages.vue index c06be22..d9a3bd2 100644 --- a/ui/src/views/SelectPackages.vue +++ b/ui/src/views/SelectPackages.vue @@ -1,6 +1,7 @@