mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-04-21 11:26:15 +02:00
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
This commit is contained in:
@@ -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`.
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<OsString>,
|
||||
/// 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<UpdaterEndpoint>,
|
||||
/// Additional arguments given to the NSIS or WiX installer.
|
||||
#[serde(default, alias = "installer-args")]
|
||||
pub installer_args: Vec<String>,
|
||||
/// Updater pubkey used to verify signatures.
|
||||
pub pubkey: String,
|
||||
/// Updater config options specific to windows.
|
||||
pub windows: Option<WindowsConfig>,
|
||||
}
|
||||
|
||||
/// A URL to an updater server.
|
||||
|
||||
@@ -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`.")]
|
||||
|
||||
@@ -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<R: Runtime, T: Manager<R>> UpdaterExt<R> 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::<UpdaterState>().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<String>,
|
||||
installer_args: Option<Vec<String>>,
|
||||
pubkey: Option<String>,
|
||||
installer_args: Vec<OsString>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
@@ -121,25 +128,50 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn pubkey<S: Into<String>>(mut self, pubkey: S) -> Self {
|
||||
self.pubkey.replace(pubkey.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn installer_args<I, S>(mut self, args: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: Into<String>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
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::<Vec<_>>();
|
||||
self.installer_args.extend_from_slice(&args);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn installer_arg<S>(mut self, arg: S) -> Self
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
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<R: Runtime>(self) -> TauriPlugin<R, Config> {
|
||||
let pubkey = self.pubkey;
|
||||
let target = self.target;
|
||||
let installer_args = self.installer_args;
|
||||
PluginBuilder::<R, Config>::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(())
|
||||
|
||||
@@ -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<Box<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>>,
|
||||
executable_path: Option<PathBuf>,
|
||||
target: Option<String>,
|
||||
@@ -98,19 +98,19 @@ pub struct UpdaterBuilder {
|
||||
headers: HeaderMap,
|
||||
timeout: Option<Duration>,
|
||||
proxy: Option<Url>,
|
||||
installer_args: Option<Vec<String>>,
|
||||
installer_args: Vec<OsString>,
|
||||
}
|
||||
|
||||
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<S: Into<String>>(mut self, pubkey: S) -> Self {
|
||||
self.config.pubkey = pubkey.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn installer_arg<S>(mut self, arg: S) -> Self
|
||||
where
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
self.installer_args.push(arg.as_ref().to_os_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn installer_args<I, S>(mut self, args: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: Into<String>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
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::<Vec<_>>();
|
||||
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<Updater> {
|
||||
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<Box<dyn Fn(Version, RemoteRelease) -> bool + Send + Sync>>,
|
||||
timeout: Option<Duration>,
|
||||
proxy: Option<Url>,
|
||||
endpoints: Vec<Url>,
|
||||
#[allow(dead_code)]
|
||||
installer_args: Vec<String>,
|
||||
installer_args: Vec<OsString>,
|
||||
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<String>,
|
||||
/// Version used to check for update
|
||||
@@ -375,7 +395,7 @@ pub struct Update {
|
||||
#[allow(unused)]
|
||||
extract_path: PathBuf,
|
||||
#[allow(unused)]
|
||||
installer_args: Vec<String>,
|
||||
installer_args: Vec<OsString>,
|
||||
/// 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<u8>) -> 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::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
self.installer_args
|
||||
.iter()
|
||||
.map(AsRef::as_ref)
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
.map(|a| a.as_os_str())
|
||||
.collect::<Vec<_>>(),
|
||||
]
|
||||
.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::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_default(),
|
||||
self.installer_args
|
||||
.iter()
|
||||
.map(AsRef::as_ref)
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice(),
|
||||
.map(|a| a.as_os_str())
|
||||
.collect::<Vec<_>>(),
|
||||
]
|
||||
.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<u8>) -> 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()?;
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user