Bladeren bron

feat(bundler): add post/pre install/remove scripts for linux deb and rpm packages (#9209)

* feat(cli/add): add post/pre install/remove scripts for linux

* fix(cli): clippy errors

* fix(cli): remove script struct from deb/rpm bundle

* change files and aliases
Vladimir Stoilov 1 jaar geleden
bovenliggende
commit
259d845290

+ 5 - 0
.changes/deb-rpm-post-pre-scripts-bundler.md

@@ -0,0 +1,5 @@
+---
+'tauri-bundler': 'minor:feat'
+---
+
+Add suport for include `preinstall`, `postinstall`, `preremove` and `postremove` scripts into Debian and RPM packages.

+ 5 - 0
.changes/deb-rpm-post-pre-scripts-config.md

@@ -0,0 +1,5 @@
+---
+'tauri-utils': 'minor:feat'
+---
+
+Added `preInstallScript`, `postInstallScript`, `preRemoveScript` and `postRemoveScript` options for `bundler > deb` and `bundler > rpm` configs.

+ 62 - 6
core/tauri-config-schema/schema.json

@@ -2430,6 +2430,27 @@
             "type": "string"
           }
         },
+        "section": {
+          "description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "priority": {
+          "description": "Change the priority of the Debian Package. By default, it is set to `optional`. Recognized Priorities as of now are :  `required`, `important`, `standard`, `optional`, `extra`",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "changelog": {
+          "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "desktopTemplate": {
           "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.",
           "type": [
@@ -2437,22 +2458,29 @@
             "null"
           ]
         },
-        "section": {
-          "description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections",
+        "preInstallScript": {
+          "description": "Path to script that will be executed before the package is unpacked. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
           "type": [
             "string",
             "null"
           ]
         },
-        "priority": {
-          "description": "Change the priority of the Debian Package. By default, it is set to `optional`. Recognized Priorities as of now are :  `required`, `important`, `standard`, `optional`, `extra`",
+        "postInstallScript": {
+          "description": "Path to script that will be executed after the package is unpacked. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
           "type": [
             "string",
             "null"
           ]
         },
-        "changelog": {
-          "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
+        "preRemoveScript": {
+          "description": "Path to script that will be executed before the package is removed. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "postRemoveScript": {
+          "description": "Path to script that will be executed after the package is removed. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
           "type": [
             "string",
             "null"
@@ -2501,6 +2529,34 @@
             "string",
             "null"
           ]
+        },
+        "preInstallScript": {
+          "description": "Path to script that will be executed before the package is unpacked. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "postInstallScript": {
+          "description": "Path to script that will be executed after the package is unpacked. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "preRemoveScript": {
+          "description": "Path to script that will be executed before the package is removed. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "postRemoveScript": {
+          "description": "Path to script that will be executed after the package is removed. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
         }
       },
       "additionalProperties": false

+ 42 - 4
core/tauri-utils/src/config.rs

@@ -326,10 +326,6 @@ pub struct DebConfig {
   /// The files to include on the package.
   #[serde(default)]
   pub files: HashMap<PathBuf, PathBuf>,
-  /// Path to a custom desktop file Handlebars template.
-  ///
-  /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
-  pub desktop_template: Option<PathBuf>,
   /// Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
   pub section: Option<String>,
   /// Change the priority of the Debian Package. By default, it is set to `optional`.
@@ -338,6 +334,27 @@ pub struct DebConfig {
   /// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
   /// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes
   pub changelog: Option<PathBuf>,
+  /// Path to a custom desktop file Handlebars template.
+  ///
+  /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
+  #[serde(alias = "desktop-template")]
+  pub desktop_template: Option<PathBuf>,
+  /// Path to script that will be executed before the package is unpacked. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  #[serde(alias = "pre-install-script")]
+  pub pre_install_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is unpacked. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  #[serde(alias = "post-install-script")]
+  pub post_install_script: Option<PathBuf>,
+  /// Path to script that will be executed before the package is removed. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  #[serde(alias = "pre-remove-script")]
+  pub pre_remove_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is removed. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  #[serde(alias = "post-remove-script")]
+  pub post_remove_script: Option<PathBuf>,
 }
 
 /// Configuration for Linux bundles.
@@ -379,7 +396,24 @@ pub struct RpmConfig {
   /// Path to a custom desktop file Handlebars template.
   ///
   /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
+  #[serde(alias = "desktop-template")]
   pub desktop_template: Option<PathBuf>,
+  /// Path to script that will be executed before the package is unpacked. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  #[serde(alias = "pre-install-script")]
+  pub pre_install_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is unpacked. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  #[serde(alias = "post-install-script")]
+  pub post_install_script: Option<PathBuf>,
+  /// Path to script that will be executed before the package is removed. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  #[serde(alias = "pre-remove-script")]
+  pub pre_remove_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is removed. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  #[serde(alias = "post-remove-script")]
+  pub post_remove_script: Option<PathBuf>,
 }
 
 impl Default for RpmConfig {
@@ -390,6 +424,10 @@ impl Default for RpmConfig {
       epoch: 0,
       files: Default::default(),
       desktop_template: None,
+      pre_install_script: None,
+      post_install_script: None,
+      pre_remove_script: None,
+      post_remove_script: None,
     }
   }
 }

+ 38 - 2
tooling/bundler/src/bundle/linux/debian.rs

@@ -32,9 +32,9 @@ use tar::HeaderMode;
 use walkdir::WalkDir;
 
 use std::{
-  fs::{self, File},
+  fs::{self, File, OpenOptions},
   io::{self, Write},
-  os::unix::fs::MetadataExt,
+  os::unix::fs::{MetadataExt, OpenOptionsExt},
   path::{Path, PathBuf},
 };
 
@@ -76,6 +76,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
   let control_dir = package_dir.join("control");
   generate_control_file(settings, arch, &control_dir, &data_dir)
     .with_context(|| "Failed to create control file")?;
+  generate_scripts(settings, &control_dir).with_context(|| "Failed to create control scripts")?;
   generate_md5sums(&control_dir, &data_dir).with_context(|| "Failed to create md5sums file")?;
 
   // Generate `debian-binary` file; see
@@ -202,6 +203,41 @@ fn generate_control_file(
   Ok(())
 }
 
+fn generate_scripts(settings: &Settings, control_dir: &Path) -> crate::Result<()> {
+  if let Some(script_path) = &settings.deb().pre_install_script {
+    let dest_path = control_dir.join("preinst");
+    create_script_file_from_path(script_path, &dest_path)?
+  }
+
+  if let Some(script_path) = &settings.deb().post_install_script {
+    let dest_path = control_dir.join("postinst");
+    create_script_file_from_path(script_path, &dest_path)?
+  }
+
+  if let Some(script_path) = &settings.deb().pre_remove_script {
+    let dest_path = control_dir.join("prerm");
+    create_script_file_from_path(script_path, &dest_path)?
+  }
+
+  if let Some(script_path) = &settings.deb().post_remove_script {
+    let dest_path = control_dir.join("postrm");
+    create_script_file_from_path(script_path, &dest_path)?
+  }
+  Ok(())
+}
+
+fn create_script_file_from_path(from: &PathBuf, to: &PathBuf) -> crate::Result<()> {
+  let mut from = File::open(from)?;
+  let mut file = OpenOptions::new()
+    .create(true)
+    .truncate(true)
+    .write(true)
+    .mode(0o755)
+    .open(to)?;
+  std::io::copy(&mut from, &mut file)?;
+  Ok(())
+}
+
 /// Create an `md5sums` file in the `control_dir` containing the MD5 checksums
 /// for each file within the `data_dir`.
 fn generate_md5sums(control_dir: &Path, data_dir: &Path) -> crate::Result<()> {

+ 21 - 0
tooling/bundler/src/bundle/linux/rpm.rs

@@ -78,6 +78,27 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
     builder = builder.with_file(&src, FileOptions::new(dest.to_string_lossy()))?;
   }
 
+  // Add scripts
+  if let Some(script_path) = &settings.rpm().pre_install_script {
+    let script = fs::read_to_string(script_path)?;
+    builder = builder.pre_install_script(script);
+  }
+
+  if let Some(script_path) = &settings.rpm().post_install_script {
+    let script = fs::read_to_string(script_path)?;
+    builder = builder.post_install_script(script);
+  }
+
+  if let Some(script_path) = &settings.rpm().pre_remove_script {
+    let script = fs::read_to_string(script_path)?;
+    builder = builder.pre_uninstall_script(script);
+  }
+
+  if let Some(script_path) = &settings.rpm().post_remove_script {
+    let script = fs::read_to_string(script_path)?;
+    builder = builder.post_uninstall_script(script);
+  }
+
   // Add resources
   if settings.resource_files().count() > 0 {
     let resource_dir = Path::new("/usr/lib").join(settings.main_binary_name());

+ 24 - 0
tooling/bundler/src/bundle/settings.rs

@@ -188,6 +188,18 @@ pub struct DebianSettings {
   /// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
   /// https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes
   pub changelog: Option<PathBuf>,
+  /// Path to script that will be executed before the package is unpacked. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  pub pre_install_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is unpacked. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  pub post_install_script: Option<PathBuf>,
+  /// Path to script that will be executed before the package is removed. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  pub pre_remove_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is removed. See
+  /// https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html
+  pub post_remove_script: Option<PathBuf>,
 }
 
 /// The Linux AppImage bundle settings.
@@ -218,6 +230,18 @@ pub struct RpmSettings {
   #[doc = include_str!("./linux/templates/main.desktop")]
   /// ```
   pub desktop_template: Option<PathBuf>,
+  /// Path to script that will be executed before the package is unpacked. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  pub pre_install_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is unpacked. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  pub post_install_script: Option<PathBuf>,
+  /// Path to script that will be executed before the package is removed. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  pub pre_remove_script: Option<PathBuf>,
+  /// Path to script that will be executed after the package is removed. See
+  /// http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html
+  pub post_remove_script: Option<PathBuf>,
 }
 
 /// Position coordinates struct.

+ 62 - 6
tooling/cli/schema.json

@@ -2430,6 +2430,27 @@
             "type": "string"
           }
         },
+        "section": {
+          "description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "priority": {
+          "description": "Change the priority of the Debian Package. By default, it is set to `optional`. Recognized Priorities as of now are :  `required`, `important`, `standard`, `optional`, `extra`",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "changelog": {
+          "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "desktopTemplate": {
           "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.",
           "type": [
@@ -2437,22 +2458,29 @@
             "null"
           ]
         },
-        "section": {
-          "description": "Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections",
+        "preInstallScript": {
+          "description": "Path to script that will be executed before the package is unpacked. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
           "type": [
             "string",
             "null"
           ]
         },
-        "priority": {
-          "description": "Change the priority of the Debian Package. By default, it is set to `optional`. Recognized Priorities as of now are :  `required`, `important`, `standard`, `optional`, `extra`",
+        "postInstallScript": {
+          "description": "Path to script that will be executed after the package is unpacked. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
           "type": [
             "string",
             "null"
           ]
         },
-        "changelog": {
-          "description": "Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes",
+        "preRemoveScript": {
+          "description": "Path to script that will be executed before the package is removed. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "postRemoveScript": {
+          "description": "Path to script that will be executed after the package is removed. See https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html",
           "type": [
             "string",
             "null"
@@ -2501,6 +2529,34 @@
             "string",
             "null"
           ]
+        },
+        "preInstallScript": {
+          "description": "Path to script that will be executed before the package is unpacked. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "postInstallScript": {
+          "description": "Path to script that will be executed after the package is unpacked. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "preRemoveScript": {
+          "description": "Path to script that will be executed before the package is removed. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
+        "postRemoveScript": {
+          "description": "Path to script that will be executed after the package is removed. See http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html",
+          "type": [
+            "string",
+            "null"
+          ]
         }
       },
       "additionalProperties": false

+ 8 - 0
tooling/cli/src/interface/rust.rs

@@ -1335,6 +1335,10 @@ fn tauri_config_to_bundle_settings(
       section: config.linux.deb.section,
       priority: config.linux.deb.priority,
       changelog: config.linux.deb.changelog,
+      pre_install_script: config.linux.deb.pre_install_script,
+      post_install_script: config.linux.deb.post_install_script,
+      pre_remove_script: config.linux.deb.pre_remove_script,
+      post_remove_script: config.linux.deb.post_remove_script,
     },
     appimage: AppImageSettings {
       files: config.linux.appimage.files,
@@ -1349,6 +1353,10 @@ fn tauri_config_to_bundle_settings(
       epoch: config.linux.rpm.epoch,
       files: config.linux.rpm.files,
       desktop_template: config.linux.rpm.desktop_template,
+      pre_install_script: config.linux.rpm.pre_install_script,
+      post_install_script: config.linux.rpm.post_install_script,
+      pre_remove_script: config.linux.rpm.pre_remove_script,
+      post_remove_script: config.linux.rpm.post_remove_script,
     },
     dmg: DmgSettings {
       background: config.macos.dmg.background,