From 09e89537b38c74732a6f63ef154705496e5dc1fb Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Fri, 13 Sep 2024 17:56:40 -0300 Subject: [PATCH 1/4] fix(core): `restart` cannot handle binary name change on macOS Tauri v2 changed the default binary name of the bundled apps (no longer follows the productName, just uses the default name from Cargo instead). This breaks the `restart` function, which expects the current binary path to match the new one. Due to this change, the restart() function for macOS is broken - the .app is correctly replaced even if the productName changed, but the restart() function cannot handle the new binary path. This change adds a simple check on macOS to read the `Contents/MacOS` folder and if it only contains a single binary, we use it to restart instead. This inference cannot be used if there's sidecars, so in this case we just let the existing implementation run and if it fails to restart, we do not panic but only warn and exit instead. AppImage updates are not affected by this, and the Windows installer is responsible for restarting, so this change is only applied to macOS binaries. --- .changes/fix-restart-macos.md | 6 ++++ core/tauri/src/api/process.rs | 47 ++++++++++++++++++++++++++++--- examples/api/src-tauri/Cargo.lock | 14 ++++----- 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 .changes/fix-restart-macos.md diff --git a/.changes/fix-restart-macos.md b/.changes/fix-restart-macos.md new file mode 100644 index 00000000000..b7db3b53646 --- /dev/null +++ b/.changes/fix-restart-macos.md @@ -0,0 +1,6 @@ +--- +"tauri": patch:bug +--- + +Fixes the restart() function not being compatible with the v2 binary name change. +Additionally, do not panic if we somehow failed to restart, and only exit instead. diff --git a/core/tauri/src/api/process.rs b/core/tauri/src/api/process.rs index 1cb4c0e0885..03b8547883f 100644 --- a/core/tauri/src/api/process.rs +++ b/core/tauri/src/api/process.rs @@ -82,10 +82,49 @@ pub fn restart(env: &Env) { use std::process::{exit, Command}; if let Ok(path) = current_binary(env) { - Command::new(path) - .args(&env.args) - .spawn() - .expect("application failed to start"); + // on macOS on updates the binary name might have changed + // so we'll read the Contents/MacOS folder instead to infer the actual binary path + #[cfg(target_os = "macos")] + if let Some(parent) = path.parent() { + if parent.components().last() + == Some(std::path::Component::Normal(std::ffi::OsStr::new("MacOS"))) + { + let macos_binaries = std::fs::read_dir(parent) + .map(|dir| { + dir + .into_iter() + .flatten() + .map(|entry| entry.path()) + .collect::>() + }) + .unwrap_or_default(); + match macos_binaries.len() { + 0 => { + // should never happen, but let's not panic here since it's a crucial feature for updates + exit(1); + } + 1 => { + // we have one binary (no sidecar) so we should use it to restart + if let Err(e) = Command::new(macos_binaries.first().unwrap()) + .args(&env.args) + .spawn() + { + eprintln!("failed to restart app: {e}"); + } + + exit(0); + } + _ => { + // in case of sidecars we don't have enough information here to decide what's the right binary name + // so let's hope the binary name didn't change by running the Command::spawn below + } + } + } + } + + if let Err(e) = Command::new(path).args(&env.args).spawn() { + eprintln!("failed to restart app: {e}"); + } } exit(0); diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 65e4049085b..af3f065ec5f 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -4027,7 +4027,7 @@ checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" [[package]] name = "tauri" -version = "1.7.1" +version = "1.7.2" dependencies = [ "anyhow", "base64 0.22.1", @@ -4093,7 +4093,7 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.3" +version = "1.5.4" dependencies = [ "anyhow", "cargo_toml", @@ -4112,7 +4112,7 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.4" +version = "1.4.5" dependencies = [ "base64 0.21.7", "brotli", @@ -4136,7 +4136,7 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.5" +version = "1.4.6" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4148,7 +4148,7 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.4" +version = "0.14.5" dependencies = [ "gtk", "http", @@ -4167,7 +4167,7 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.9" +version = "0.14.10" dependencies = [ "arboard", "cocoa 0.24.1", @@ -4186,7 +4186,7 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.6.0" +version = "1.6.1" dependencies = [ "aes-gcm", "brotli", From 92ad508c5a2a04c381234c8e6a22f54756b99fa8 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 14 Sep 2024 07:43:03 -0300 Subject: [PATCH 2/4] fix: use Info.plist to determine binary name --- Cargo.lock | 1 + core/tauri/Cargo.toml | 1 + core/tauri/src/api/process.rs | 80 +++++++++++++++++-------------- examples/api/src-tauri/Cargo.lock | 1 + 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index adbb582cb71..c0469966e38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4100,6 +4100,7 @@ dependencies = [ "os_info", "os_pipe", "percent-encoding", + "plist", "png", "proptest", "quickcheck", diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index b0cd6ef9596..81f28294c2a 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -114,6 +114,7 @@ nix = { version = "0.26.0", default-features = false, features = [ "user", "sock [target."cfg(target_os = \"macos\")".dependencies] embed_plist = "1.2" +plist = "1" cocoa = "0.24" # wry still uses 0.24 objc = "0.2" # Do not update without consensus diff --git a/core/tauri/src/api/process.rs b/core/tauri/src/api/process.rs index 03b8547883f..3868a3748e4 100644 --- a/core/tauri/src/api/process.rs +++ b/core/tauri/src/api/process.rs @@ -83,44 +83,9 @@ pub fn restart(env: &Env) { if let Ok(path) = current_binary(env) { // on macOS on updates the binary name might have changed - // so we'll read the Contents/MacOS folder instead to infer the actual binary path + // so we'll read the Contents/Info.plist file to determine the binary path #[cfg(target_os = "macos")] - if let Some(parent) = path.parent() { - if parent.components().last() - == Some(std::path::Component::Normal(std::ffi::OsStr::new("MacOS"))) - { - let macos_binaries = std::fs::read_dir(parent) - .map(|dir| { - dir - .into_iter() - .flatten() - .map(|entry| entry.path()) - .collect::>() - }) - .unwrap_or_default(); - match macos_binaries.len() { - 0 => { - // should never happen, but let's not panic here since it's a crucial feature for updates - exit(1); - } - 1 => { - // we have one binary (no sidecar) so we should use it to restart - if let Err(e) = Command::new(macos_binaries.first().unwrap()) - .args(&env.args) - .spawn() - { - eprintln!("failed to restart app: {e}"); - } - - exit(0); - } - _ => { - // in case of sidecars we don't have enough information here to decide what's the right binary name - // so let's hope the binary name didn't change by running the Command::spawn below - } - } - } - } + restart_macos_app(&path, env); if let Err(e) = Command::new(path).args(&env.args).spawn() { eprintln!("failed to restart app: {e}"); @@ -129,3 +94,44 @@ pub fn restart(env: &Env) { exit(0); } + +#[cfg(target_os = "macos")] +fn restart_macos_app(current_binary: &PathBuf, env: &Env) { + use std::process::{exit, Command}; + + if let Some(macos_directory) = current_binary.parent() { + if macos_directory.components().last() + != Some(std::path::Component::Normal(std::ffi::OsStr::new("MacOS"))) + { + return; + } + + if let Some(contents_directory) = macos_directory.parent() { + if contents_directory.components().last() + != Some(std::path::Component::Normal(std::ffi::OsStr::new( + "Contents", + ))) + { + return; + } + + if let Ok(info_plist) = + plist::from_file::<_, plist::Dictionary>(contents_directory.join("Info.plist")) + { + if let Some(binary_name) = info_plist + .get("CFBundleExecutable") + .and_then(|v| v.as_string()) + { + if let Err(e) = Command::new(macos_directory.join(binary_name)) + .args(&env.args) + .spawn() + { + eprintln!("failed to restart app: {e}"); + } + + exit(0); + } + } + } + } +} diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index af3f065ec5f..7770d1ebf93 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -4059,6 +4059,7 @@ dependencies = [ "os_info", "os_pipe", "percent-encoding", + "plist", "png", "rand 0.8.5", "raw-window-handle", From fba9d543e11f70ddd8e2c680357760c7b9de52d1 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 14 Sep 2024 10:02:28 -0300 Subject: [PATCH 3/4] use log instead of eprintln --- Cargo.lock | 1 + core/tauri/Cargo.toml | 1 + core/tauri/src/api/process.rs | 4 ++-- examples/api/src-tauri/Cargo.lock | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0469966e38..660a8116ea0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4090,6 +4090,7 @@ dependencies = [ "ignore", "indexmap", "infer", + "log", "minisign-verify", "mockito", "nix 0.26.4", diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index 81f28294c2a..aa8834f30a3 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -115,6 +115,7 @@ nix = { version = "0.26.0", default-features = false, features = [ "user", "sock [target."cfg(target_os = \"macos\")".dependencies] embed_plist = "1.2" plist = "1" +log = "0.4" cocoa = "0.24" # wry still uses 0.24 objc = "0.2" # Do not update without consensus diff --git a/core/tauri/src/api/process.rs b/core/tauri/src/api/process.rs index 3868a3748e4..476aa38314f 100644 --- a/core/tauri/src/api/process.rs +++ b/core/tauri/src/api/process.rs @@ -88,7 +88,7 @@ pub fn restart(env: &Env) { restart_macos_app(&path, env); if let Err(e) = Command::new(path).args(&env.args).spawn() { - eprintln!("failed to restart app: {e}"); + log::error!("failed to restart app: {e}"); } } @@ -126,7 +126,7 @@ fn restart_macos_app(current_binary: &PathBuf, env: &Env) { .args(&env.args) .spawn() { - eprintln!("failed to restart app: {e}"); + log::error!("failed to restart app: {e}"); } exit(0); diff --git a/examples/api/src-tauri/Cargo.lock b/examples/api/src-tauri/Cargo.lock index 7770d1ebf93..e2a446c53a3 100644 --- a/examples/api/src-tauri/Cargo.lock +++ b/examples/api/src-tauri/Cargo.lock @@ -4050,6 +4050,7 @@ dependencies = [ "ignore", "indexmap 1.9.3", "infer", + "log", "minisign-verify", "nix", "notify-rust", From 5cac77290ad0652d8dc8ff16a8f499b7f780d94a Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sat, 14 Sep 2024 10:07:40 -0300 Subject: [PATCH 4/4] move log --- core/tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tauri/Cargo.toml b/core/tauri/Cargo.toml index aa8834f30a3..5b94553f76c 100644 --- a/core/tauri/Cargo.toml +++ b/core/tauri/Cargo.toml @@ -101,6 +101,7 @@ sys-locale = { version = "0.3", optional = true } tracing = { version = "0.1", optional = true } indexmap = { version = "1", features = [ "std", "serde" ], optional = true } getrandom = { version = "0.2", features = [ "std" ] } +log = "0.4" [target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies] rfd = { version = "0.10", optional = true, features = [ "gtk3", "common-controls-v6" ] } # 0.11 raised gtk version @@ -115,7 +116,6 @@ nix = { version = "0.26.0", default-features = false, features = [ "user", "sock [target."cfg(target_os = \"macos\")".dependencies] embed_plist = "1.2" plist = "1" -log = "0.4" cocoa = "0.24" # wry still uses 0.24 objc = "0.2" # Do not update without consensus