From 96e3528a7c7b0ac4649b2ccfcb04bfffada5b139 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 12 Mar 2024 18:54:46 +0800 Subject: [PATCH 1/8] Fix updater doesn't cleanup before exit --- plugins/updater/src/commands.rs | 1 + plugins/updater/src/updater.rs | 31 +++++++++++-------- plugins/updater/tests/app-updater/src/main.rs | 6 +++- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/plugins/updater/src/commands.rs b/plugins/updater/src/commands.rs index 6d2668f24..0f5f76c95 100644 --- a/plugins/updater/src/commands.rs +++ b/plugins/updater/src/commands.rs @@ -87,6 +87,7 @@ pub(crate) async fn download_and_install( update .download_and_install( + app.app_handle(), |chunk_length, content_length| { if first_chunk { first_chunk = !first_chunk; diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index 4ba744358..1d4177d9b 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -21,7 +21,7 @@ use reqwest::{ }; use semver::Version; use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize}; -use tauri::{utils::platform::current_exe, Resource}; +use tauri::{utils::platform::current_exe, AppHandle, Resource}; use time::OffsetDateTime; use url::Url; @@ -475,22 +475,27 @@ impl Update { } /// Installs the updater package downloaded by [`Update::download`] - pub fn install(&self, bytes: Vec) -> Result<()> { - self.install_inner(bytes) + pub fn install(&self, app: &AppHandle, bytes: Vec) -> Result<()> { + self.install_inner(app, bytes) } /// Downloads and installs the updater package - pub async fn download_and_install), D: FnOnce()>( + pub async fn download_and_install< + R: tauri::Runtime, + C: FnMut(usize, Option), + D: FnOnce(), + >( &self, + app: &AppHandle, on_chunk: C, on_download_finish: D, ) -> Result<()> { let bytes = self.download(on_chunk, on_download_finish).await?; - self.install(bytes) + self.install(app, bytes) } #[cfg(mobile)] - fn install_inner(&self, bytes: Vec) -> Result<()> { + fn install_inner(&self, _app: &AppHandle, _bytes: Vec) -> Result<()> { Ok(()) } @@ -511,7 +516,7 @@ impl Update { // ## EXE // Update server can provide a custom EXE (installer) who can run any task. #[cfg(windows)] - fn install_inner(&self, bytes: Vec) -> Result<()> { + fn install_inner(&self, app: &AppHandle, bytes: Vec) -> Result<()> { use std::fs; use windows_sys::{ w, @@ -557,9 +562,11 @@ impl Update { continue; } + app.cleanup_before_exit(); + let file = encode_wide(found_path.as_os_str()); let parameters = encode_wide(installer_args.join(OsStr::new(" ")).as_os_str()); - let ret = unsafe { + unsafe { ShellExecuteW( 0, w!("open"), @@ -569,9 +576,7 @@ impl Update { SW_SHOW, ) }; - if ret <= 32 { - return Err(Error::Io(std::io::Error::last_os_error())); - } + std::process::exit(0); } @@ -595,7 +600,7 @@ impl Update { target_os = "netbsd", target_os = "openbsd" ))] - fn install_inner(&self, bytes: Vec) -> Result<()> { + fn install_inner(&self, _app: &AppHandle, bytes: Vec) -> Result<()> { use flate2::read::GzDecoder; use std::os::unix::fs::{MetadataExt, PermissionsExt}; let archive = Cursor::new(bytes); @@ -661,7 +666,7 @@ impl Update { // │ └── ... // └── ... #[cfg(target_os = "macos")] - fn install_inner(&self, bytes: Vec) -> Result<()> { + fn install_inner(&self, _app: &AppHandle, bytes: Vec) -> Result<()> { use flate2::read::GzDecoder; let cursor = Cursor::new(bytes); diff --git a/plugins/updater/tests/app-updater/src/main.rs b/plugins/updater/tests/app-updater/src/main.rs index ad145c499..493dc4c8b 100644 --- a/plugins/updater/tests/app-updater/src/main.rs +++ b/plugins/updater/tests/app-updater/src/main.rs @@ -4,6 +4,7 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use tauri::Manager; use tauri_plugin_updater::UpdaterExt; fn main() { @@ -35,7 +36,10 @@ fn main() { match updater.check().await { Ok(Some(update)) => { - if let Err(e) = update.download_and_install(|_, _| {}, || {}).await { + if let Err(e) = update + .download_and_install(handle.app_handle(), |_, _| {}, || {}) + .await + { println!("{e}"); std::process::exit(1); } From 448afe4042a9d24826023d185e61449965384aaf Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 13 Mar 2024 10:35:50 +0800 Subject: [PATCH 2/8] Add change file --- .changes/fix-updater-cleanup-md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changes/fix-updater-cleanup-md diff --git a/.changes/fix-updater-cleanup-md b/.changes/fix-updater-cleanup-md new file mode 100644 index 000000000..e49224ae0 --- /dev/null +++ b/.changes/fix-updater-cleanup-md @@ -0,0 +1,7 @@ +--- +"updater": patch +--- + +Fix updater doesn't shutdown the app gracefully on update + +**Breaking change** `Update::download_and_install` now takes `AppHandle` as its first parameter From b4185edae406f110c343e95c5c2671df49ab5e24 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 13 Mar 2024 21:24:21 +0800 Subject: [PATCH 3/8] Add a on_before_exit function instead --- .changes/fix-updater-cleanup-md | 4 +- .../updater/permissions/schemas/schema.json | 10 +++-- plugins/updater/src/commands.rs | 1 - plugins/updater/src/lib.rs | 5 +++ plugins/updater/src/updater.rs | 43 ++++++++++++------- plugins/updater/tests/app-updater/src/main.rs | 5 +-- 6 files changed, 41 insertions(+), 27 deletions(-) diff --git a/.changes/fix-updater-cleanup-md b/.changes/fix-updater-cleanup-md index e49224ae0..647d827a1 100644 --- a/.changes/fix-updater-cleanup-md +++ b/.changes/fix-updater-cleanup-md @@ -2,6 +2,4 @@ "updater": patch --- -Fix updater doesn't shutdown the app gracefully on update - -**Breaking change** `Update::download_and_install` now takes `AppHandle` as its first parameter +Add a `on_before_exit` hook for cleanup before spawning the updater on Windows, defaults to `app.cleanup_before_exit` diff --git a/plugins/updater/permissions/schemas/schema.json b/plugins/updater/permissions/schemas/schema.json index 691359767..6d6a3c211 100644 --- a/plugins/updater/permissions/schemas/schema.json +++ b/plugins/updater/permissions/schemas/schema.json @@ -139,10 +139,14 @@ }, "platforms": { "description": "Target platforms this permission applies. By default all platforms are affected by this permission.", - "type": [ - "array", - "null" + "default": [ + "linux", + "macOS", + "windows", + "android", + "iOS" ], + "type": "array", "items": { "$ref": "#/definitions/Target" } diff --git a/plugins/updater/src/commands.rs b/plugins/updater/src/commands.rs index 0f5f76c95..6d2668f24 100644 --- a/plugins/updater/src/commands.rs +++ b/plugins/updater/src/commands.rs @@ -87,7 +87,6 @@ pub(crate) async fn download_and_install( update .download_and_install( - app.app_handle(), |chunk_length, content_length| { if first_chunk { first_chunk = !first_chunk; diff --git a/plugins/updater/src/lib.rs b/plugins/updater/src/lib.rs index e060827d2..37198150d 100644 --- a/plugins/updater/src/lib.rs +++ b/plugins/updater/src/lib.rs @@ -98,6 +98,11 @@ impl> UpdaterExt for T { } } + let app_handle = app.app_handle().clone(); + builder = builder.on_before_exit(move || { + app_handle.cleanup_before_exit(); + }); + builder } diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index 1d4177d9b..0bb9c7996 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -8,6 +8,7 @@ use std::{ io::{Cursor, Read}, path::{Path, PathBuf}, str::FromStr, + sync::Arc, time::Duration, }; @@ -21,7 +22,7 @@ use reqwest::{ }; use semver::Version; use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize}; -use tauri::{utils::platform::current_exe, AppHandle, Resource}; +use tauri::{utils::platform::current_exe, Resource}; use time::OffsetDateTime; use url::Url; @@ -88,6 +89,8 @@ impl RemoteRelease { } } +pub type OnBeforeExit = Arc () + Send + Sync + 'static>; + pub struct UpdaterBuilder { current_version: Version, config: Config, @@ -99,6 +102,7 @@ pub struct UpdaterBuilder { timeout: Option, proxy: Option, installer_args: Vec, + on_before_exit: Option, } impl UpdaterBuilder { @@ -118,6 +122,7 @@ impl UpdaterBuilder { headers: Default::default(), timeout: None, proxy: None, + on_before_exit: None, } } @@ -197,6 +202,11 @@ impl UpdaterBuilder { self } + pub fn on_before_exit () + Send + Sync + 'static>(mut self, f: F) -> Self { + self.on_before_exit.replace(Arc::new(f)); + self + } + pub fn build(self) -> Result { let endpoints = self .endpoints @@ -236,6 +246,7 @@ impl UpdaterBuilder { json_target, headers: self.headers, extract_path, + on_before_exit: self.on_before_exit, }) } } @@ -256,6 +267,7 @@ pub struct Updater { json_target: String, headers: HeaderMap, extract_path: PathBuf, + on_before_exit: Option, } impl Updater { @@ -354,6 +366,7 @@ impl Updater { let update = if should_update { Some(Update { config: self.config.clone(), + on_before_exit: self.on_before_exit.clone(), current_version: self.current_version.to_string(), target: self.target.clone(), extract_path: self.extract_path.clone(), @@ -375,9 +388,10 @@ impl Updater { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct Update { config: Config, + on_before_exit: Option, /// Update description pub body: Option, /// Version used to check for update @@ -475,27 +489,22 @@ impl Update { } /// Installs the updater package downloaded by [`Update::download`] - pub fn install(&self, app: &AppHandle, bytes: Vec) -> Result<()> { - self.install_inner(app, bytes) + pub fn install(&self, bytes: Vec) -> Result<()> { + self.install_inner(bytes) } /// Downloads and installs the updater package - pub async fn download_and_install< - R: tauri::Runtime, - C: FnMut(usize, Option), - D: FnOnce(), - >( + pub async fn download_and_install), D: FnOnce()>( &self, - app: &AppHandle, on_chunk: C, on_download_finish: D, ) -> Result<()> { let bytes = self.download(on_chunk, on_download_finish).await?; - self.install(app, bytes) + self.install(bytes) } #[cfg(mobile)] - fn install_inner(&self, _app: &AppHandle, _bytes: Vec) -> Result<()> { + fn install_inner(&self, _bytes: Vec) -> Result<()> { Ok(()) } @@ -516,7 +525,7 @@ impl Update { // ## EXE // Update server can provide a custom EXE (installer) who can run any task. #[cfg(windows)] - fn install_inner(&self, app: &AppHandle, bytes: Vec) -> Result<()> { + fn install_inner(&self, bytes: Vec) -> Result<()> { use std::fs; use windows_sys::{ w, @@ -562,7 +571,9 @@ impl Update { continue; } - app.cleanup_before_exit(); + if let Some(on_before_exit) = self.on_before_exit.as_ref() { + on_before_exit(); + } let file = encode_wide(found_path.as_os_str()); let parameters = encode_wide(installer_args.join(OsStr::new(" ")).as_os_str()); @@ -600,7 +611,7 @@ impl Update { target_os = "netbsd", target_os = "openbsd" ))] - fn install_inner(&self, _app: &AppHandle, bytes: Vec) -> Result<()> { + fn install_inner(&self, bytes: Vec) -> Result<()> { use flate2::read::GzDecoder; use std::os::unix::fs::{MetadataExt, PermissionsExt}; let archive = Cursor::new(bytes); @@ -666,7 +677,7 @@ impl Update { // │ └── ... // └── ... #[cfg(target_os = "macos")] - fn install_inner(&self, _app: &AppHandle, bytes: Vec) -> Result<()> { + fn install_inner(&self, bytes: Vec) -> Result<()> { use flate2::read::GzDecoder; let cursor = Cursor::new(bytes); diff --git a/plugins/updater/tests/app-updater/src/main.rs b/plugins/updater/tests/app-updater/src/main.rs index 493dc4c8b..99aea091d 100644 --- a/plugins/updater/tests/app-updater/src/main.rs +++ b/plugins/updater/tests/app-updater/src/main.rs @@ -36,10 +36,7 @@ fn main() { match updater.check().await { Ok(Some(update)) => { - if let Err(e) = update - .download_and_install(handle.app_handle(), |_, _| {}, || {}) - .await - { + if let Err(e) = update.download_and_install(|_, _| {}, || {}).await { println!("{e}"); std::process::exit(1); } From 39812b45a86952a4a8b80913fd1c6356a0196dc1 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 13 Mar 2024 21:26:15 +0800 Subject: [PATCH 4/8] Cleanup --- plugins/updater/tests/app-updater/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/updater/tests/app-updater/src/main.rs b/plugins/updater/tests/app-updater/src/main.rs index 99aea091d..ad145c499 100644 --- a/plugins/updater/tests/app-updater/src/main.rs +++ b/plugins/updater/tests/app-updater/src/main.rs @@ -4,7 +4,6 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use tauri::Manager; use tauri_plugin_updater::UpdaterExt; fn main() { From 6d5702a0896c27ab5b8161e332d0b15898aed304 Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Wed, 13 Mar 2024 15:44:27 +0200 Subject: [PATCH 5/8] Update .changes/fix-updater-cleanup-md --- .changes/fix-updater-cleanup-md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changes/fix-updater-cleanup-md b/.changes/fix-updater-cleanup-md index 647d827a1..fe69a0049 100644 --- a/.changes/fix-updater-cleanup-md +++ b/.changes/fix-updater-cleanup-md @@ -2,4 +2,4 @@ "updater": patch --- -Add a `on_before_exit` hook for cleanup before spawning the updater on Windows, defaults to `app.cleanup_before_exit` +Add a `on_before_exit` hook for cleanup before spawning the updater on Windows, defaults to `app.cleanup_before_exit` when used through `UpdaterExt` From ac56dd9205177bacd9d3975e8b85a687bbd3511d Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 13 Mar 2024 21:45:51 +0800 Subject: [PATCH 6/8] Clean up --- plugins/updater/src/updater.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index 0bb9c7996..5ba070dc7 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -89,7 +89,7 @@ impl RemoteRelease { } } -pub type OnBeforeExit = Arc () + Send + Sync + 'static>; +pub type OnBeforeExit = Arc; pub struct UpdaterBuilder { current_version: Version, @@ -202,7 +202,7 @@ impl UpdaterBuilder { self } - pub fn on_before_exit () + Send + Sync + 'static>(mut self, f: F) -> Self { + pub fn on_before_exit(mut self, f: F) -> Self { self.on_before_exit.replace(Arc::new(f)); self } From b09e1f14ac8e9f7ce84d6a62d2296ef60d627607 Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Wed, 13 Mar 2024 15:52:32 +0200 Subject: [PATCH 7/8] Update plugins/updater/src/updater.rs --- plugins/updater/src/updater.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index 5ba070dc7..de2ef2fd8 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -391,6 +391,7 @@ impl Updater { #[derive(Clone)] pub struct Update { config: Config, + #[allow(unused)] on_before_exit: Option, /// Update description pub body: Option, From a1caab072fa0988e492665a697f4d3af528c16e7 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 13 Mar 2024 21:54:09 +0800 Subject: [PATCH 8/8] Clippy --- plugins/updater/src/updater.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index de2ef2fd8..27749bc37 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -556,7 +556,7 @@ impl Update { let mut installer_args = self .installer_args .iter() - .map(|a| OsStr::new(a)) + .map(OsStr::new) .collect::>(); for path in paths {