From 506ce4835bc206bf6ae2edf82bf88633274d25cf Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Sat, 3 Feb 2024 14:14:39 +0200 Subject: [PATCH] refactor(updater): accomodate to new tauri config restructure (#924) * refactor(updater): accomodate to new tauri config restructure RFC#5 https://github.com/tauri-apps/rfcs/blob/f3e82a6b0c5390401e855850d47dc7b7d9afd684/texts/0005-tauri-config-restructure.md RFC#5 PR implementation: https://github.com/tauri-apps/tauri/pull/8723 * lint and update configs --- .changes/updater.md | 21 +++ examples/api/src-tauri/tauri.conf.json | 104 +++++++-------- .../examples/app/src-tauri/tauri.conf.json | 60 +++------ plugins/dialog/test/tauri.conf.json | 17 ++- plugins/notification/test/tauri.conf.json | 17 ++- .../vanilla/src-tauri/tauri.conf.json | 55 +++----- plugins/updater/src/config.rs | 75 ++++++++++- plugins/updater/src/error.rs | 4 +- plugins/updater/src/lib.rs | 48 +++++-- plugins/updater/src/updater.rs | 121 ++++++++++++------ .../updater/tests/app-updater/tauri.conf.json | 51 +++----- .../svelte-app/src-tauri/tauri.conf.json | 47 +++---- 12 files changed, 349 insertions(+), 271 deletions(-) create mode 100644 .changes/updater.md diff --git a/.changes/updater.md b/.changes/updater.md new file mode 100644 index 00000000..83b83bd8 --- /dev/null +++ b/.changes/updater.md @@ -0,0 +1,21 @@ +--- +"updater": "patch" +--- + +Refactored the updater plugin to accommodate to the new changes in tauri config: + +- JSON plugin config: + + - Added `pubkey` option. + - Added `windows` option which is a Windows-specific options. + - Renamed `installer_args` to `installerArgs`. + - Moved `installerArgs` option to the new `windows` object. + +- Rust crate changes: + - Added `pubkey` field for `Config`. + - Added `windows` field for `Config` option which is a Windows-specific options. + - Added `WindowsConfig` and `WindowsUpdateInstallMode`. + - Moved `installerArgs` option to the new `windows` object. + - Added `Builder::pubkey` and `UpdaterBuilder::pubkey`. + - Changed `Builder::installer_args` and `UpdaterBuilder::installer_args` to add to existing installer args, instead of replacing them, use `Builder/UpdaterBuilder::clear_installer_args` to clear existing args. + - Added `Builder::installer_arg`, `Builder::clear_installer_args`, `UpdaterBuilder::installer_arg` and `UpdaterBuilder::clear_installer_args`. diff --git a/examples/api/src-tauri/tauri.conf.json b/examples/api/src-tauri/tauri.conf.json index 02fd5c3b..cab20220 100644 --- a/examples/api/src-tauri/tauri.conf.json +++ b/examples/api/src-tauri/tauri.conf.json @@ -1,15 +1,40 @@ { "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "productName": "Tauri API", + "version": "2.0.0", + "identifier": "com.tauri.api", "build": { - "distDir": "../dist", - "devPath": "http://localhost:5173", + "devUrl": "http://localhost:5173", + "frontendDist": "../dist", "beforeDevCommand": "yarn dev", - "beforeBuildCommand": "yarn build", - "withGlobalTauri": true + "beforeBuildCommand": "yarn build" }, - "package": { - "productName": "Tauri API", - "version": "2.0.0" + "app": { + "withGlobalTauri": true, + "macOSPrivateApi": true, + "security": { + "pattern": { + "use": "isolation", + "options": { + "dir": "../isolation-dist/" + } + }, + "csp": { + "default-src": "'self' customprotocol: asset:", + "connect-src": "ipc: http://ipc.localhost", + "font-src": ["https://fonts.gstatic.com"], + "img-src": "'self' asset: http://asset.localhost blob: data:", + "style-src": "'unsafe-inline' 'self' http://fonts.googleapis.com" + }, + "freezePrototype": true, + "assetProtocol": { + "enable": true, + "scope": { + "allow": ["$APPDATA/db/**", "$RESOURCE/**"], + "deny": ["$APPDATA/db/*.stronghold"] + } + } + } }, "plugins": { "cli": { @@ -84,58 +109,27 @@ "updater": { "endpoints": [ "https://tauri-update-server.vercel.app/update/{{target}}/{{current_version}}" - ] + ], + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK" } }, - "tauri": { - "pattern": { - "use": "isolation", - "options": { - "dir": "../isolation-dist/" - } - }, - "macOSPrivateApi": true, - "bundle": { - "active": true, - "identifier": "com.tauri.api", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "windows": { - "wix": { - "language": { - "en-US": {}, - "pt-BR": { - "localePath": "locales/pt-BR.wxl" - } + "bundle": { + "active": true, + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "windows": { + "wix": { + "language": { + "en-US": {}, + "pt-BR": { + "localePath": "locales/pt-BR.wxl" } } - }, - "updater": { - "active": true, - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE5QzMxNjYwNTM5OEUwNTgKUldSWTRKaFRZQmJER1h4d1ZMYVA3dnluSjdpN2RmMldJR09hUFFlZDY0SlFqckkvRUJhZDJVZXAK" - } - }, - "windows": [], - "security": { - "csp": { - "default-src": "'self' customprotocol: asset:", - "connect-src": "ipc: http://ipc.localhost", - "font-src": ["https://fonts.gstatic.com"], - "img-src": "'self' asset: http://asset.localhost blob: data:", - "style-src": "'unsafe-inline' 'self' http://fonts.googleapis.com" - }, - "freezePrototype": true, - "assetProtocol": { - "enable": true, - "scope": { - "allow": ["$APPDATA/db/**", "$RESOURCE/**"], - "deny": ["$APPDATA/db/*.stronghold"] - } } } } diff --git a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json index ef467e44..f95b1d7c 100644 --- a/plugins/deep-link/examples/app/src-tauri/tauri.conf.json +++ b/plugins/deep-link/examples/app/src-tauri/tauri.conf.json @@ -1,49 +1,14 @@ { + "productName": "deep-link-example", + "version": "0.0.0", + "identifier": "com.tauri.deep-link-example", "build": { + "devUrl": "http://localhost:1420", + "frontendDist": "../dist", "beforeDevCommand": "pnpm dev", - "beforeBuildCommand": "pnpm build", - "devPath": "http://localhost:1420", - "distDir": "../dist", - "withGlobalTauri": false + "beforeBuildCommand": "pnpm build" }, - "package": { - "productName": "deep-link-example", - "version": "0.0.0" - }, - "tauri": { - "bundle": { - "active": true, - "category": "DeveloperTool", - "copyright": "", - "deb": { - "depends": [] - }, - "externalBin": [], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "identifier": "com.tauri.deep-link-example", - "longDescription": "", - "macOS": { - "entitlements": null, - "exceptionDomain": "", - "frameworks": [], - "providerShortName": null, - "signingIdentity": null - }, - "resources": [], - "shortDescription": "", - "targets": "all", - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, + "app": { "security": { "csp": null }, @@ -68,5 +33,16 @@ { "host": "tauri.app" } ] } + }, + "bundle": { + "active": true, + "category": "DeveloperTool", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] } } diff --git a/plugins/dialog/test/tauri.conf.json b/plugins/dialog/test/tauri.conf.json index c4a453d9..83cda94c 100644 --- a/plugins/dialog/test/tauri.conf.json +++ b/plugins/dialog/test/tauri.conf.json @@ -1,15 +1,10 @@ { - "$schema": "../../../node_modules/.pnpm/@tauri-apps+cli@2.0.0-alpha.17/node_modules/@tauri-apps/cli/schema.json", + "identifier": "studio.tauri.example", "build": { - "distDir": ".", - "devPath": "http://localhost:4000" + "frontendDist": ".", + "devUrl": "http://localhost:4000" }, - "tauri": { - "bundle": { - "identifier": "studio.tauri.example", - "active": true, - "icon": ["../../../examples/api/src-tauri/icons/icon.png"] - }, + "app": { "windows": [ { "title": "Tauri App" @@ -18,5 +13,9 @@ "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: http://tauri.localhost 'unsafe-eval' 'unsafe-inline' 'self'" } + }, + "bundle": { + "active": true, + "icon": ["../../../examples/api/src-tauri/icons/icon.png"] } } diff --git a/plugins/notification/test/tauri.conf.json b/plugins/notification/test/tauri.conf.json index c4a453d9..83cda94c 100644 --- a/plugins/notification/test/tauri.conf.json +++ b/plugins/notification/test/tauri.conf.json @@ -1,15 +1,10 @@ { - "$schema": "../../../node_modules/.pnpm/@tauri-apps+cli@2.0.0-alpha.17/node_modules/@tauri-apps/cli/schema.json", + "identifier": "studio.tauri.example", "build": { - "distDir": ".", - "devPath": "http://localhost:4000" + "frontendDist": ".", + "devUrl": "http://localhost:4000" }, - "tauri": { - "bundle": { - "identifier": "studio.tauri.example", - "active": true, - "icon": ["../../../examples/api/src-tauri/icons/icon.png"] - }, + "app": { "windows": [ { "title": "Tauri App" @@ -18,5 +13,9 @@ "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: http://tauri.localhost 'unsafe-eval' 'unsafe-inline' 'self'" } + }, + "bundle": { + "active": true, + "icon": ["../../../examples/api/src-tauri/icons/icon.png"] } } diff --git a/plugins/single-instance/examples/vanilla/src-tauri/tauri.conf.json b/plugins/single-instance/examples/vanilla/src-tauri/tauri.conf.json index ee356ba2..8f9a852d 100644 --- a/plugins/single-instance/examples/vanilla/src-tauri/tauri.conf.json +++ b/plugins/single-instance/examples/vanilla/src-tauri/tauri.conf.json @@ -1,45 +1,11 @@ { - "package": { - "productName": "app", - "version": "0.1.0" - }, + "productName": "app", + "version": "0.1.0", + "identifier": "com.tauri.single-instance", "build": { - "distDir": "../public", - "devPath": "../public" + "frontendDist": "../public" }, - "tauri": { - "bundle": { - "active": true, - "targets": "all", - "identifier": "com.tauri.single-instance", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "resources": [], - "externalBin": [], - "copyright": "", - "category": "DeveloperTool", - "shortDescription": "", - "longDescription": "", - "deb": { - "depends": [] - }, - "macOS": { - "frameworks": [], - "exceptionDomain": "", - "signingIdentity": null, - "entitlements": null - }, - "windows": { - "certificateThumbprint": null, - "digestAlgorithm": "sha256", - "timestampUrl": "" - } - }, + "app": { "windows": [ { "title": "app", @@ -52,5 +18,16 @@ "security": { "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: http://tauri.localhost 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self'" } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] } } diff --git a/plugins/updater/src/config.rs b/plugins/updater/src/config.rs index 4fa85183..84835b3b 100644 --- a/plugins/updater/src/config.rs +++ b/plugins/updater/src/config.rs @@ -2,17 +2,86 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +use std::{ffi::OsString, fmt::Display}; + use serde::{Deserialize, Deserializer}; use url::Url; +/// Install modes for the Windows update. +#[derive(Debug, PartialEq, Eq, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum WindowsUpdateInstallMode { + /// Specifies there's a basic UI during the installation process, including a final dialog box at the end. + BasicUi, + /// The quiet mode means there's no user interaction required. + /// Requires admin privileges if the installer does. + Quiet, + /// Specifies unattended mode, which means the installation only shows a progress bar. + Passive, +} + +impl WindowsUpdateInstallMode { + /// Returns the associated `msiexec.exe` arguments. + pub fn msiexec_args(&self) -> &'static [&'static str] { + match self { + Self::BasicUi => &["/qb+"], + Self::Quiet => &["/quiet"], + Self::Passive => &["/passive"], + } + } + + /// Returns the associated nsis arguments. + pub fn nsis_args(&self) -> &'static [&'static str] { + match self { + Self::Passive => &["/P", "/R"], + Self::Quiet => &["/S", "/R"], + _ => &[], + } + } +} + +impl Display for WindowsUpdateInstallMode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Self::BasicUi => "basicUI", + Self::Quiet => "quiet", + Self::Passive => "passive", + } + ) + } +} + +impl Default for WindowsUpdateInstallMode { + fn default() -> Self { + Self::Passive + } +} + +#[derive(Debug, Clone, Deserialize, Default)] +#[serde(rename_all = "camelCase")] +pub struct WindowsConfig { + /// Additional arguments given to the NSIS or WiX installer. + #[serde(default)] + pub installer_args: Vec, + /// Updating mode, see [`WindowsUpdateInstallMode`] for more info. + #[serde(default)] + pub install_mode: WindowsUpdateInstallMode, +} + /// Updater configuration. #[derive(Debug, Clone, Deserialize, Default)] +#[serde(rename_all = "camelCase")] pub struct Config { + /// Updater endpoints. #[serde(default)] pub endpoints: Vec, - /// Additional arguments given to the NSIS or WiX installer. - #[serde(default, alias = "installer-args")] - pub installer_args: Vec, + /// Updater pubkey used to verify signatures. + pub pubkey: String, + /// Updater config options specific to windows. + pub windows: Option, } /// A URL to an updater server. diff --git a/plugins/updater/src/error.rs b/plugins/updater/src/error.rs index 3b927b74..43c0d2cb 100644 --- a/plugins/updater/src/error.rs +++ b/plugins/updater/src/error.rs @@ -25,9 +25,7 @@ pub enum Error { #[error("Could not fetch a valid release JSON from the remote")] ReleaseNotFound, /// Unsupported app architecture. - #[error( - "Unsupported application architecture, expected one of `x86`, `x86_64`, `arm` or `aarch64`." - )] + #[error("Unsupported application architecture, expected one of `x86`, `x86_64`, `arm` or `aarch64`.")] UnsupportedArch, /// Operating system is not supported. #[error("Unsupported OS, expected one of `linux`, `darwin` or `windows`.")] diff --git a/plugins/updater/src/lib.rs b/plugins/updater/src/lib.rs index 71cf6e78..8c0ea2cb 100644 --- a/plugins/updater/src/lib.rs +++ b/plugins/updater/src/lib.rs @@ -13,6 +13,8 @@ html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png" )] +use std::ffi::{OsStr, OsString}; + use tauri::{ plugin::{Builder as PluginBuilder, TauriPlugin}, Manager, Runtime, @@ -69,15 +71,19 @@ impl> UpdaterExt for T { fn updater_builder(&self) -> UpdaterBuilder { let app = self.app_handle(); let version = app.package_info().version.clone(); - let updater_config = app.config().tauri.bundle.updater.clone(); let UpdaterState { config, target } = self.state::().inner(); - let mut builder = UpdaterBuilder::new(version, config.clone(), updater_config); + let mut builder = UpdaterBuilder::new(version, config.clone()); if let Some(target) = target { builder = builder.target(target); } + let args = self.env().args_os; + if !args.is_empty() { + builder = builder.installer_arg("/ARGS").installer_args(args); + } + #[cfg(any( target_os = "linux", target_os = "dragonfly", @@ -108,7 +114,8 @@ struct UpdaterState { #[derive(Default)] pub struct Builder { target: Option, - installer_args: Option>, + pubkey: Option, + installer_args: Vec, } impl Builder { @@ -121,25 +128,50 @@ impl Builder { self } + pub fn pubkey>(mut self, pubkey: S) -> Self { + self.pubkey.replace(pubkey.into()); + self + } + pub fn installer_args(mut self, args: I) -> Self where I: IntoIterator, - S: Into, + S: AsRef, { - self.installer_args - .replace(args.into_iter().map(Into::into).collect()); + let args = args + .into_iter() + .map(|a| a.as_ref().to_os_string()) + .collect::>(); + self.installer_args.extend_from_slice(&args); + self + } + + pub fn installer_arg(mut self, arg: S) -> Self + where + S: AsRef, + { + self.installer_args.push(arg.as_ref().to_os_string()); + self + } + + pub fn clear_installer_args(mut self) -> Self { + self.installer_args.clear(); self } pub fn build(self) -> TauriPlugin { + let pubkey = self.pubkey; let target = self.target; let installer_args = self.installer_args; PluginBuilder::::new("updater") .js_init_script(include_str!("api-iife.js").to_string()) .setup(move |app, api| { let mut config = api.config().clone(); - if let Some(installer_args) = installer_args { - config.installer_args = installer_args; + if let Some(pubkey) = pubkey { + config.pubkey = pubkey; + } + if let Some(windows) = &mut config.windows { + windows.installer_args.extend_from_slice(&installer_args); } app.manage(UpdaterState { target, config }); Ok(()) diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index 59e0383a..a77d0af5 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -4,6 +4,7 @@ use std::{ collections::HashMap, + ffi::{OsStr, OsString}, io::{Cursor, Read}, path::{Path, PathBuf}, str::FromStr, @@ -20,14 +21,14 @@ use reqwest::{ }; use semver::Version; use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize}; -use tauri::{ - utils::{config::UpdaterConfig, platform::current_exe}, - Resource, -}; +use tauri::{utils::platform::current_exe, Resource}; use time::OffsetDateTime; use url::Url; -use crate::error::{Error, Result}; +use crate::{ + error::{Error, Result}, + Config, +}; #[derive(Debug, Deserialize, Serialize, Clone)] pub struct ReleaseManifestPlatform { @@ -89,8 +90,7 @@ impl RemoteRelease { pub struct UpdaterBuilder { current_version: Version, - config: crate::Config, - updater_config: UpdaterConfig, + config: Config, version_comparator: Option bool + Send + Sync>>, executable_path: Option, target: Option, @@ -98,19 +98,19 @@ pub struct UpdaterBuilder { headers: HeaderMap, timeout: Option, proxy: Option, - installer_args: Option>, + installer_args: Vec, } impl UpdaterBuilder { - pub fn new( - current_version: Version, - config: crate::Config, - updater_config: UpdaterConfig, - ) -> Self { + pub fn new(current_version: Version, config: crate::Config) -> Self { Self { + installer_args: config + .windows + .as_ref() + .map(|w| w.installer_args.clone()) + .unwrap_or_default(), current_version, config, - updater_config, version_comparator: None, executable_path: None, target: None, @@ -118,7 +118,6 @@ impl UpdaterBuilder { headers: Default::default(), timeout: None, proxy: None, - installer_args: None, } } @@ -170,20 +169,41 @@ impl UpdaterBuilder { self } + pub fn pubkey>(mut self, pubkey: S) -> Self { + self.config.pubkey = pubkey.into(); + self + } + + pub fn installer_arg(mut self, arg: S) -> Self + where + S: AsRef, + { + self.installer_args.push(arg.as_ref().to_os_string()); + self + } + pub fn installer_args(mut self, args: I) -> Self where I: IntoIterator, - S: Into, + S: AsRef, { - self.installer_args - .replace(args.into_iter().map(Into::into).collect()); + let args = args + .into_iter() + .map(|a| a.as_ref().to_os_string()) + .collect::>(); + self.installer_args.extend_from_slice(&args); + self + } + + pub fn clear_installer_args(mut self) -> Self { + self.installer_args.clear(); self } pub fn build(self) -> Result { let endpoints = self .endpoints - .unwrap_or_else(|| self.config.endpoints.into_iter().map(|e| e.0).collect()); + .unwrap_or_else(|| self.config.endpoints.iter().map(|e| e.0.clone()).collect()); if endpoints.is_empty() { return Err(Error::EmptyEndpoints); @@ -207,13 +227,13 @@ impl UpdaterBuilder { }; Ok(Updater { - config: self.updater_config, + config: self.config, current_version: self.current_version, version_comparator: self.version_comparator, timeout: self.timeout, proxy: self.proxy, endpoints, - installer_args: self.installer_args.unwrap_or(self.config.installer_args), + installer_args: self.installer_args, arch, target, json_target, @@ -224,14 +244,14 @@ impl UpdaterBuilder { } pub struct Updater { - config: UpdaterConfig, + config: Config, current_version: Version, version_comparator: Option bool + Send + Sync>>, timeout: Option, proxy: Option, endpoints: Vec, #[allow(dead_code)] - installer_args: Vec, + installer_args: Vec, arch: &'static str, // The `{{target}}` variable we replace in the endpoint target: String, @@ -336,8 +356,8 @@ impl Updater { let update = if should_update { Some(Update { - current_version: self.current_version.to_string(), config: self.config.clone(), + current_version: self.current_version.to_string(), target: self.target.clone(), extract_path: self.extract_path.clone(), installer_args: self.installer_args.clone(), @@ -360,7 +380,7 @@ impl Updater { #[derive(Debug, Clone)] pub struct Update { - config: UpdaterConfig, + config: Config, /// Update description pub body: Option, /// Version used to check for update @@ -375,7 +395,7 @@ pub struct Update { #[allow(unused)] extract_path: PathBuf, #[allow(unused)] - installer_args: Vec, + installer_args: Vec, /// Download URL announced pub download_url: Url, /// Signature announced @@ -495,7 +515,7 @@ impl Update { // Update server can provide a custom EXE (installer) who can run any task. #[cfg(windows)] fn install_inner(&self, bytes: Vec) -> Result<()> { - use std::{ffi::OsStr, fs, process::Command}; + use std::{fs, process::Command}; // FIXME: We need to create a memory buffer with the MSI and then run it. // (instead of extracting the MSI to a temp path) @@ -535,12 +555,21 @@ impl Update { installer_path.push("\""); let installer_args = [ - self.config.windows.install_mode.nsis_args(), + self.config + .windows + .as_ref() + .map(|w| { + w.install_mode + .nsis_args() + .iter() + .map(|a| OsStr::new(a)) + .collect::>() + }) + .unwrap_or_default(), self.installer_args .iter() - .map(AsRef::as_ref) - .collect::>() - .as_slice(), + .map(|a| a.as_os_str()) + .collect::>(), ] .concat(); @@ -552,7 +581,8 @@ impl Update { .arg(installer_path); if !installer_args.is_empty() { - cmd.arg("-ArgumentList").arg(installer_args.join(", ")); + cmd.arg("-ArgumentList") + .arg(installer_args.join(OsStr::new(", "))); } cmd.spawn().expect("installer failed to start"); @@ -570,12 +600,21 @@ impl Update { msi_path.push("\"\"\""); let installer_args = [ - self.config.windows.install_mode.msiexec_args(), + self.config + .windows + .as_ref() + .map(|w| { + w.install_mode + .msiexec_args() + .iter() + .map(|a| OsStr::new(a)) + .collect::>() + }) + .unwrap_or_default(), self.installer_args .iter() - .map(AsRef::as_ref) - .collect::>() - .as_slice(), + .map(|a| a.as_os_str()) + .collect::>(), ] .concat(); @@ -591,7 +630,10 @@ impl Update { ]) .arg("/i,") .arg(&msi_path) - .arg(format!(", {}, /promptrestart;", installer_args.join(", "))) + .arg(format!( + ", {}, /promptrestart;", + installer_args.join(OsStr::new(", ")).to_string_lossy() + )) .arg("Start-Process") .arg(current_exe_arg) .spawn(); @@ -636,10 +678,7 @@ impl Update { ))] fn install_inner(&self, bytes: Vec) -> Result<()> { use flate2::read::GzDecoder; - use std::{ - ffi::OsStr, - os::unix::fs::{MetadataExt, PermissionsExt}, - }; + use std::os::unix::fs::{MetadataExt, PermissionsExt}; let archive = Cursor::new(bytes); let extract_path_metadata = self.extract_path.metadata()?; diff --git a/plugins/updater/tests/app-updater/tauri.conf.json b/plugins/updater/tests/app-updater/tauri.conf.json index 9727f0d8..5eb96954 100644 --- a/plugins/updater/tests/app-updater/tauri.conf.json +++ b/plugins/updater/tests/app-updater/tauri.conf.json @@ -1,39 +1,28 @@ { - "$schema": "../../../../node_modules/.pnpm/@tauri-apps+cli@2.0.0-alpha.17/node_modules/@tauri-apps/cli/schema.json", - "build": { - "distDir": [], - "devPath": [] - }, - "tauri": { - "bundle": { - "active": true, - "targets": "all", - "identifier": "com.tauri.updater", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "category": "DeveloperTool", + "identifier": "com.tauri.updater", + "plugins": { + "updater": { + "endpoints": ["http://localhost:3007"], + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEMwNjY1MEExMTFBMDU5RTUKUldUbFdhQVJvVkJtd09sZ1ROT25yVGFhU2o0ZnUyd1FlT0ZTQ2ZXamN3SXk4SjZLZmNwRnV5dTMK", "windows": { - "wix": { - "skipWebviewInstall": true - } - }, - "updater": { - "active": true, - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEMwNjY1MEExMTFBMDU5RTUKUldUbFdhQVJvVkJtd09sZ1ROT25yVGFhU2o0ZnUyd1FlT0ZTQ2ZXamN3SXk4SjZLZmNwRnV5dTMK", - "windows": { - "installMode": "quiet" - } + "installMode": "quiet" } } }, - "plugins": { - "updater": { - "endpoints": ["http://localhost:3007"] + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "windows": { + "wix": { + "skipWebviewInstall": true + } } } } diff --git a/plugins/websocket/examples/svelte-app/src-tauri/tauri.conf.json b/plugins/websocket/examples/svelte-app/src-tauri/tauri.conf.json index 205771f4..c4fe3f7f 100644 --- a/plugins/websocket/examples/svelte-app/src-tauri/tauri.conf.json +++ b/plugins/websocket/examples/svelte-app/src-tauri/tauri.conf.json @@ -1,38 +1,12 @@ { + "identifier": "com.tauri.dev", "build": { - "distDir": "../build", - "devPath": "http://localhost:5173/", + "devUrl": "http://localhost:5173/", + "frontendDist": "../build", "beforeDevCommand": "pnpm dev", - "beforeBuildCommand": "pnpm build", - "withGlobalTauri": false + "beforeBuildCommand": "pnpm build" }, - "tauri": { - "bundle": { - "active": true, - "targets": "all", - "identifier": "com.tauri.dev", - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "resources": [], - "externalBin": [], - "copyright": "", - "category": "DeveloperTool", - "shortDescription": "", - "longDescription": "", - "deb": { - "depends": [] - }, - "macOS": { - "frameworks": [], - "minimumSystemVersion": "", - "exceptionDomain": "" - } - }, + "app": { "windows": [ { "title": "Tauri App", @@ -45,5 +19,16 @@ "security": { "csp": null } + }, + "bundle": { + "active": true, + "targets": "all", + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ] } }