diff --git a/.changes/restart-handle-binary-name-change.md b/.changes/restart-handle-binary-name-change.md new file mode 100644 index 000000000000..5ea8f79c7ff1 --- /dev/null +++ b/.changes/restart-handle-binary-name-change.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:enhance +--- + +Handle macOS binary name change on the `process::restart` function. diff --git a/Cargo.lock b/Cargo.lock index c573557e5bee..9c681fd6b24f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7031,6 +7031,7 @@ dependencies = [ "muda", "objc", "percent-encoding", + "plist", "proptest", "quickcheck", "quickcheck_macros", diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml index 1c6ae2ef66dd..78cc7e8cb380 100644 --- a/crates/tauri/Cargo.toml +++ b/crates/tauri/Cargo.toml @@ -103,6 +103,7 @@ webkit2gtk = { version = "=2.0.1", features = ["v2_40"] } [target."cfg(target_os = \"macos\")".dependencies] embed_plist = "1.2" +plist = "1" cocoa = "0.26" objc = "0.2" window-vibrancy = "0.5" diff --git a/crates/tauri/src/process.rs b/crates/tauri/src/process.rs index 5fb3c44e798c..47fdd341241a 100644 --- a/crates/tauri/src/process.rs +++ b/crates/tauri/src/process.rs @@ -75,12 +75,59 @@ pub fn restart(env: &Env) -> ! { use std::process::{exit, Command}; if let Ok(path) = current_binary(env) { - Command::new(path) - // first arg is the binary name, must skip it + // on macOS on updates the binary name might have changed + // so we'll read the Contents/Info.plist file to determine the binary path + #[cfg(target_os = "macos")] + restart_macos_app(&path, env); + + if let Err(e) = Command::new(path) .args(env.args_os.iter().skip(1).collect::>()) .spawn() - .expect("application failed to start"); + { + log::error!("failed to restart app: {e}"); + } } 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_os.iter().skip(1).collect::>()) + .spawn() + { + log::error!("failed to restart app: {e}"); + } + + exit(0); + } + } + } + } +}