From 36e80fc8fb6ec756c4a15f81811f9cff29995272 Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Sun, 1 Dec 2024 22:18:54 +0000 Subject: [PATCH] Vastly simplify windows update for now --- Cargo.lock | 10 -- src/bins/Cargo.toml | 2 +- src/bins/src/commands/apply_windows_impl.rs | 130 ++++++++++---------- src/bins/src/shared/util_common.rs | 50 +++----- src/bins/src/windows/mod.rs | 2 +- 5 files changed, 88 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25ff0315..a604f2ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -740,15 +740,6 @@ dependencies = [ "flate2", ] -[[package]] -name = "filelocksmith" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e811394ea0b0e8c2a01a2abcf10aed8328d8df81402e80ab6727d75a08712e21" -dependencies = [ - "cc", -] - [[package]] name = "flate2" version = "1.0.35" @@ -2306,7 +2297,6 @@ dependencies = [ "dialog", "enum-flags", "file-rotate", - "filelocksmith", "fs_extra", "glob", "image", diff --git a/src/bins/Cargo.toml b/src/bins/Cargo.toml index 9a0e60de..5734bcfe 100644 --- a/src/bins/Cargo.toml +++ b/src/bins/Cargo.toml @@ -105,7 +105,7 @@ webview2-com = "0.33" libloading.workspace = true strsim.workspace = true same-file.workspace = true -filelocksmith.workspace = true +# filelocksmith.workspace = true [dev-dependencies] tempfile.workspace = true diff --git a/src/bins/src/commands/apply_windows_impl.rs b/src/bins/src/commands/apply_windows_impl.rs index b7a60ac0..47014171 100644 --- a/src/bins/src/commands/apply_windows_impl.rs +++ b/src/bins/src/commands/apply_windows_impl.rs @@ -1,46 +1,46 @@ use crate::{ dialogs, shared::{self}, - windows::locksmith, + // windows::locksmith, windows::splash, }; -use anyhow::{bail, Result}; +use anyhow::{bail, Context, Result}; use std::sync::mpsc; use std::{ fs, path::{Path, PathBuf}, }; -use velopack::{bundle::load_bundle_from_file, locator::VelopackLocator, constants}; +use velopack::{bundle::load_bundle_from_file, constants, locator::VelopackLocator}; -fn ropycopy, P2: AsRef>(source: &P1, dest: &P2) -> Result<()> { - let source = source.as_ref(); - let dest = dest.as_ref(); +// fn ropycopy, P2: AsRef>(source: &P1, dest: &P2) -> Result<()> { +// let source = source.as_ref(); +// let dest = dest.as_ref(); - // robocopy C:\source\something.new C:\destination\something /MIR /ZB /W:5 /R:5 /MT:8 /LOG:C:\logs\copy_log.txt - let cmd = std::process::Command::new("robocopy") - .arg(source) - .arg(dest) - .arg("/MIR") - .arg("/IS") - .arg("/W:1") - .arg("/R:5") - .arg("/MT:2") - .output()?; +// // robocopy C:\source\something.new C:\destination\something /MIR /ZB /W:5 /R:5 /MT:8 /LOG:C:\logs\copy_log.txt +// let cmd = std::process::Command::new("robocopy") +// .arg(source) +// .arg(dest) +// .arg("/MIR") +// .arg("/IS") +// .arg("/W:1") +// .arg("/R:5") +// .arg("/MT:2") +// .output()?; - let stdout = String::from_utf8_lossy(&cmd.stdout); - let stderr = String::from_utf8_lossy(&cmd.stderr); +// let stdout = String::from_utf8_lossy(&cmd.stdout); +// let stderr = String::from_utf8_lossy(&cmd.stderr); - let exit_code = cmd.status.code().unwrap_or(-9999); - if (0..7).contains(&exit_code) { - info!("{stdout}"); - info!("Robocopy completed successfully."); - } else { - error!("{stdout}"); - error!("{stderr}"); - bail!("Robocopy failed with code: {:?}", exit_code); - } - Ok(()) -} +// let exit_code = cmd.status.code().unwrap_or(-9999); +// if (0..7).contains(&exit_code) { +// info!("{stdout}"); +// info!("Robocopy completed successfully."); +// } else { +// error!("{stdout}"); +// error!("{stderr}"); +// bail!("Robocopy failed with code: {:?}", exit_code); +// } +// Ok(()) +// } pub fn apply_package_impl(old_locator: &VelopackLocator, package: &PathBuf, run_hooks: bool) -> Result { let mut bundle = load_bundle_from_file(package)?; @@ -87,49 +87,55 @@ pub fn apply_package_impl(old_locator: &VelopackLocator, package: &PathBuf, run_ // third, we try _REALLY HARD_ to stop the package let _ = shared::force_stop_package(root_path); - if winsafe::IsWindows10OrGreater() == Ok(true) && !locksmith::close_processes_locking_dir(&old_locator) { - bail!("Failed to close processes locking directory / user cancelled."); - } + // if winsafe::IsWindows10OrGreater() == Ok(true) && !locksmith::close_processes_locking_dir(&old_locator) { + // bail!("Failed to close processes locking directory / user cancelled."); + // } // fourth, we make as backup of the current dir to temp_path_old info!("Backing up current dir to {}", &temp_path_old.to_string_lossy()); - let mut requires_robocopy = false; - if let Err(e) = fs::rename(¤t_dir, &temp_path_old) { - warn!("Failed to rename current_dir to temp_path_old ({}). Retrying with robocopy...", e); - ropycopy(¤t_dir, &temp_path_old)?; - requires_robocopy = true; - } + shared::retry_io_ex(|| fs::rename(¤t_dir, &temp_path_old), 1000, 10) + .context("Unable to start the update, because one or more running processes prevented it.")?; + + // let mut requires_robocopy = false; + // if let Err(e) = fs::rename(¤t_dir, &temp_path_old) { + // warn!("Failed to rename current_dir to temp_path_old ({}). Retrying with robocopy...", e); + // ropycopy(¤t_dir, &temp_path_old)?; + // requires_robocopy = true; + // } // fifth, we try to replace the current dir with temp_path_new // if this fails we will yolo a rollback... info!("Replacing current dir with {}", &temp_path_new.to_string_lossy()); + shared::retry_io_ex(|| fs::rename(&temp_path_new, ¤t_dir), 1000, 30) + .context("Unable to complete the update, and the app was left in a broken state. You may need to re-install")?; - if !requires_robocopy { - // if we didn't need robocopy for the backup, we don't need it for the deploy hopefully - if let Err(e1) = fs::rename(&temp_path_new, ¤t_dir) { - warn!("Failed to rename temp_path_new to current_dir ({}). Retrying with robocopy...", e1); - requires_robocopy = true; - } - } + // if !requires_robocopy { + // // if we didn't need robocopy for the backup, we don't need it for the deploy hopefully + // if let Err(e1) = fs::rename(&temp_path_new, ¤t_dir) { + // warn!("Failed to rename temp_path_new to current_dir ({}). Retrying with robocopy...", e1); + // requires_robocopy = true; + // } + // } - if requires_robocopy { - if let Err(e2) = ropycopy(&temp_path_new, ¤t_dir) { - error!("Failed to robocopy temp_path_new to current_dir ({}). Will attempt a rollback...", e2); - let _ = ropycopy(&temp_path_old, ¤t_dir); - let _ = tx.send(splash::MSG_CLOSE); + // if requires_robocopy { + // if let Err(e2) = ropycopy(&temp_path_new, ¤t_dir) { + // error!("Failed to robocopy temp_path_new to current_dir ({}). Will attempt a rollback...", e2); + // let _ = ropycopy(&temp_path_old, ¤t_dir); + // let _ = tx.send(splash::MSG_CLOSE); - info!("Showing error dialog..."); - let title = format!("{} Update", &new_locator.get_manifest_title()); - let header = "Failed to update"; - let body = - format!("Failed to update {} to version {}. Please check the logs for more details.", - &new_locator.get_manifest_title(), - &new_locator.get_manifest_version_full_string()); - dialogs::show_error(&title, Some(header), &body); + // info!("Showing error dialog..."); + // let title = format!("{} Update", &new_locator.get_manifest_title()); + // let header = "Failed to update"; + // let body = format!( + // "Failed to update {} to version {}. Please check the logs for more details.", + // &new_locator.get_manifest_title(), + // &new_locator.get_manifest_version_full_string() + // ); + // dialogs::show_error(&title, Some(header), &body); - bail!("Fatal error performing update."); - } - } + // bail!("Fatal error performing update."); + // } + // } // from this point on, we're past the point of no return and should not bail // sixth, we write the uninstall entry @@ -146,7 +152,7 @@ pub fn apply_package_impl(old_locator: &VelopackLocator, package: &PathBuf, run_ } else { info!("Skipping uninstall entry for portable app."); } - + // seventh, we run the post-install hooks if run_hooks { crate::windows::run_hook(&new_locator, constants::HOOK_CLI_UPDATED, 15); diff --git a/src/bins/src/shared/util_common.rs b/src/bins/src/shared/util_common.rs index 337640e6..77d7c8fb 100644 --- a/src/bins/src/shared/util_common.rs +++ b/src/bins/src/shared/util_common.rs @@ -29,39 +29,25 @@ where F: Fn() -> Result, E: std::fmt::Debug, { - let res = op(); - if res.is_ok() { - return Ok(res.unwrap()); + retry_io_ex(op, 1000, 4) +} + +pub fn retry_io_ex(op: F, delay_ms: i32, count: i32) -> Result +where + F: Fn() -> Result, + E: std::fmt::Debug, +{ + let mut res = op(); + for _ in 0..count { + if res.is_ok() { + return Ok(res.unwrap()); + } + + warn!("Retrying operation in {}ms... (error was: {:?})", delay_ms, res.err()); + thread::sleep(Duration::from_millis(delay_ms as u64)); + res = op(); } - - warn!("Retrying operation in 1000ms... (error was: {:?})", res.err()); - thread::sleep(Duration::from_millis(1000)); - - let res = op(); - if res.is_ok() { - return Ok(res.unwrap()); - } - - warn!("Retrying operation in 1000ms... (error was: {:?})", res.err()); - thread::sleep(Duration::from_millis(1000)); - - let res = op(); - if res.is_ok() { - return Ok(res.unwrap()); - } - - warn!("Retrying operation in 1000ms... (error was: {:?})", res.err()); - thread::sleep(Duration::from_millis(1000)); - - let res = op(); - if res.is_ok() { - return Ok(res.unwrap()); - } - - warn!("Last retry in 1000ms... (error was: {:?})", res.err()); - thread::sleep(Duration::from_millis(1000)); - - op() + res } pub fn random_string(len: usize) -> String { diff --git a/src/bins/src/windows/mod.rs b/src/bins/src/windows/mod.rs index 838d021c..3490a561 100644 --- a/src/bins/src/windows/mod.rs +++ b/src/bins/src/windows/mod.rs @@ -1,4 +1,4 @@ -pub mod locksmith; +// pub mod locksmith; pub mod mitigate; pub mod prerequisite; pub mod runtimes;