Преглед изворни кода

fix(core): `restart` cannot handle binary name change on macOS (#10991)

* 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.

* fix: use Info.plist to determine binary name

* use log instead of eprintln

* move log
Lucas Fernandes Nogueira пре 11 месеци
родитељ
комит
26d243f43a

+ 6 - 0
.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.

+ 2 - 0
Cargo.lock

@@ -4090,6 +4090,7 @@ dependencies = [
  "ignore",
  "indexmap",
  "infer",
+ "log",
  "minisign-verify",
  "mockito",
  "nix 0.26.4",
@@ -4100,6 +4101,7 @@ dependencies = [
  "os_info",
  "os_pipe",
  "percent-encoding",
+ "plist",
  "png",
  "proptest",
  "quickcheck",

+ 2 - 0
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
@@ -114,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"
 cocoa = "0.24" # wry still uses 0.24
 objc = "0.2" # Do not update without consensus
 

+ 49 - 4
core/tauri/src/api/process.rs

@@ -82,11 +82,56 @@ 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/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).spawn() {
+      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)
+            .spawn()
+          {
+            log::error!("failed to restart app: {e}");
+          }
+
+          exit(0);
+        }
+      }
+    }
+  }
+}

+ 9 - 7
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",
@@ -4050,6 +4050,7 @@ dependencies = [
  "ignore",
  "indexmap 1.9.3",
  "infer",
+ "log",
  "minisign-verify",
  "nix",
  "notify-rust",
@@ -4059,6 +4060,7 @@ dependencies = [
  "os_info",
  "os_pipe",
  "percent-encoding",
+ "plist",
  "png",
  "rand 0.8.5",
  "raw-window-handle",
@@ -4093,7 +4095,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-build"
-version = "1.5.3"
+version = "1.5.4"
 dependencies = [
  "anyhow",
  "cargo_toml",
@@ -4112,7 +4114,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-codegen"
-version = "1.4.4"
+version = "1.4.5"
 dependencies = [
  "base64 0.21.7",
  "brotli",
@@ -4136,7 +4138,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-macros"
-version = "1.4.5"
+version = "1.4.6"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
@@ -4148,7 +4150,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime"
-version = "0.14.4"
+version = "0.14.5"
 dependencies = [
  "gtk",
  "http",
@@ -4167,7 +4169,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-runtime-wry"
-version = "0.14.9"
+version = "0.14.10"
 dependencies = [
  "arboard",
  "cocoa 0.24.1",
@@ -4186,7 +4188,7 @@ dependencies = [
 
 [[package]]
 name = "tauri-utils"
-version = "1.6.0"
+version = "1.6.1"
 dependencies = [
  "aes-gcm",
  "brotli",