Explorar el Código

fix(bundler): wrap `Exec` in desktop with quotes, rename appimage main binary if has spaces (#11218)

* fix(bundler): wrap `Exec` in desktop with quotes, rename appimage main binary if has spaces

* Update .changes/main-binary-name-spaces-linux.md [skip ci[

---------

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
Amr Bashir hace 10 meses
padre
commit
a49a19ffa3

+ 6 - 0
.changes/main-binary-name-spaces-linux.md

@@ -0,0 +1,6 @@
+---
+"tauri-bundler": "patch:bug"
+"tauri-cli": "patch:bug"
+---
+
+Fix bundling `appimage`, `deb` and `rpm` bundles failing to open when using `mainBinaryName` with spaces.

+ 21 - 6
crates/tauri-bundler/src/bundle/linux/appimage/mod.rs

@@ -15,7 +15,7 @@ use anyhow::Context;
 use handlebars::Handlebars;
 use std::{
   collections::BTreeMap,
-  fs::{remove_dir_all, write},
+  fs,
   path::PathBuf,
   process::{Command, Stdio},
 };
@@ -38,17 +38,32 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
   };
   let package_dir = settings.project_out_directory().join("bundle/appimage_deb");
 
+  let main_binary = settings.main_binary()?;
+
+  let mut settings = settings.clone();
+  if main_binary.name().contains(" ") {
+    let main_binary_path = settings.binary_path(main_binary);
+    let project_out_directory = settings.project_out_directory();
+
+    let main_binary_name_kebab = heck::AsKebabCase(main_binary.name()).to_string();
+    let new_path = project_out_directory.join(&main_binary_name_kebab);
+    fs::copy(main_binary_path, new_path)?;
+
+    let main_binary = settings.main_binary_mut()?;
+    main_binary.set_name(main_binary_name_kebab);
+  }
+
   // generate deb_folder structure
-  let (data_dir, icons) = debian::generate_data(settings, &package_dir)
+  let (data_dir, icons) = debian::generate_data(&settings, &package_dir)
     .with_context(|| "Failed to build data folders and files")?;
   common::copy_custom_files(&settings.appimage().files, &data_dir)
     .with_context(|| "Failed to copy custom files")?;
 
   let output_path = settings.project_out_directory().join("bundle/appimage");
   if output_path.exists() {
-    remove_dir_all(&output_path)?;
+    fs::remove_dir_all(&output_path)?;
   }
-  std::fs::create_dir_all(output_path.clone())?;
+  fs::create_dir_all(output_path.clone())?;
   let app_dir_path = output_path.join(format!("{}.AppDir", settings.product_name()));
   let appimage_filename = format!(
     "{}_{}_{}.AppImage",
@@ -101,7 +116,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
 
   log::info!(action = "Bundling"; "{} ({})", appimage_filename, appimage_path.display());
 
-  write(&sh_file, temp)?;
+  fs::write(&sh_file, temp)?;
 
   // chmod script for execution
   Command::new("chmod")
@@ -119,6 +134,6 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
     .output_ok()
     .context("error running build_appimage.sh")?;
 
-  remove_dir_all(&package_dir)?;
+  fs::remove_dir_all(&package_dir)?;
   Ok(vec![appimage_path])
 }

+ 8 - 1
crates/tauri-bundler/src/bundle/linux/freedesktop/mod.rs

@@ -99,6 +99,7 @@ pub fn generate_desktop_file(
   data_dir: &Path,
 ) -> crate::Result<(PathBuf, PathBuf)> {
   let bin_name = settings.main_binary_name()?;
+
   let product_name = settings.product_name();
   let desktop_file_name = format!("{product_name}.desktop");
   let path = PathBuf::from("usr/share/applications").join(desktop_file_name);
@@ -150,6 +151,12 @@ pub fn generate_desktop_file(
 
   let mime_type = (!mime_type.is_empty()).then_some(mime_type.join(";"));
 
+  let bin_name_exec = if bin_name.contains(" ") {
+    format!("\"{bin_name}\"")
+  } else {
+    bin_name.to_string()
+  };
+
   handlebars.render_to_write(
     "main.desktop",
     &DesktopTemplateParams {
@@ -162,7 +169,7 @@ pub fn generate_desktop_file(
       } else {
         None
       },
-      exec: bin_name,
+      exec: &bin_name_exec,
       icon: bin_name,
       name: settings.product_name(),
       mime_type,

+ 10 - 0
crates/tauri-bundler/src/bundle/settings.rs

@@ -889,6 +889,16 @@ impl Settings {
       .map_err(Into::into)
   }
 
+  /// Returns the file name of the binary being bundled.
+  pub fn main_binary_mut(&mut self) -> crate::Result<&mut BundleBinary> {
+    self
+      .binaries
+      .iter_mut()
+      .find(|bin| bin.main)
+      .context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")
+      .map_err(Into::into)
+  }
+
   /// Returns the file name of the binary being bundled.
   pub fn main_binary_name(&self) -> crate::Result<&str> {
     self