From b36c6001ec12c38ef03d8d9bb8fe3e20d6496780 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Mon, 19 Jun 2023 13:43:51 -0300 Subject: [PATCH] cleanup builder, fix installer and test on linux --- Cargo.lock | 177 +++++++++--------- plugins/updater/src/lib.rs | 7 +- plugins/updater/src/updater.rs | 163 ++++++++-------- .../updater/tests/app-updater/tests/update.rs | 2 +- 4 files changed, 174 insertions(+), 175 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1db4dad9..be8bc557 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -100,15 +100,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - [[package]] name = "aho-corasick" version = "1.0.1" @@ -390,28 +381,6 @@ dependencies = [ "syn 2.0.18", ] -[[package]] -name = "async-stream" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.18", -] - [[package]] name = "async-task" version = "4.4.0" @@ -638,16 +607,6 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "bstr" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "bumpalo" version = "3.13.0" @@ -695,6 +654,27 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cairo-rs" version = "0.16.7" @@ -735,6 +715,9 @@ name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cesu8" @@ -1988,19 +1971,6 @@ dependencies = [ "x11-dl", ] -[[package]] -name = "globset" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" -dependencies = [ - "aho-corasick 0.7.20", - "bstr", - "fnv", - "log", - "regex", -] - [[package]] name = "gobject-sys" version = "0.16.3" @@ -2342,23 +2312,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "ignore" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" -dependencies = [ - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", -] - [[package]] name = "image" version = "0.24.6" @@ -2615,6 +2568,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.0" @@ -3488,6 +3450,17 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "paste" version = "1.0.12" @@ -3507,6 +3480,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ "digest 0.10.7", + "hmac", + "password-hash", + "sha2 0.10.6", ] [[package]] @@ -3987,7 +3963,7 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "memchr", "regex-syntax 0.7.2", ] @@ -5300,7 +5276,7 @@ dependencies = [ name = "tauri-plugin-persisted-scope" version = "2.0.0-alpha.0" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "bincode", "log", "serde", @@ -5407,10 +5383,8 @@ version = "2.0.0-alpha.0" dependencies = [ "base64 0.21.2", "dirs-next", - "flate2", "futures-util", "http", - "ignore", "minisign-verify", "mockito", "percent-encoding", @@ -5424,7 +5398,6 @@ dependencies = [ "thiserror", "time 0.3.21", "tokio", - "tokio-test", "url", "zip", ] @@ -5786,19 +5759,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-test" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53474327ae5e166530d17f2d956afcb4f8a004de581b3cae10f12006bc8163e3" -dependencies = [ - "async-stream", - "bytes 1.4.0", - "futures-core", - "tokio", - "tokio-stream", -] - [[package]] name = "tokio-tungstenite" version = "0.19.0" @@ -7033,9 +6993,48 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" dependencies = [ + "aes 0.8.2", "byteorder", + "bzip2", + "constant_time_eq 0.1.5", "crc32fast", "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time 0.3.21", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", ] [[package]] diff --git a/plugins/updater/src/lib.rs b/plugins/updater/src/lib.rs index 0cc37c50..f4e65c48 100644 --- a/plugins/updater/src/lib.rs +++ b/plugins/updater/src/lib.rs @@ -63,11 +63,13 @@ impl> UpdaterExt for T { let version = app.package_info().version.clone(); let updater_config = app.config().tauri.bundle.updater.clone(); let UpdaterState { config, target } = self.state::().inner(); - #[allow(unused_mut)] + let mut builder = UpdaterBuilder::new(version, config.clone(), updater_config); + if let Some(target) = target { builder = builder.target(target); } + #[cfg(any( target_os = "linux", target_os = "dragonfly", @@ -78,9 +80,10 @@ impl> UpdaterExt for T { { let env = app.env(); if let Some(appimage) = env.appimage { - builder = builder.app_image_path(appimage); + builder = builder.executable_path(appimage); } } + builder } diff --git a/plugins/updater/src/updater.rs b/plugins/updater/src/updater.rs index ece195b3..3e81b649 100644 --- a/plugins/updater/src/updater.rs +++ b/plugins/updater/src/updater.rs @@ -85,10 +85,16 @@ impl RemoteRelease { } pub struct UpdaterBuilder { - updater: Updater, - target: Option, + current_version: Version, + config: crate::Config, + updater_config: UpdaterConfig, + version_comparator: Option bool + Send + Sync>>, executable_path: Option, - app_image_path: Option, + target: Option, + endpoints: Option>, + headers: HeaderMap, + timeout: Option, + installer_args: Option>, } impl UpdaterBuilder { @@ -98,10 +104,16 @@ impl UpdaterBuilder { updater_config: UpdaterConfig, ) -> Self { Self { - updater: Updater::new(current_version, config, updater_config), - target: Default::default(), - executable_path: Default::default(), - app_image_path: Default::default(), + current_version, + config, + updater_config, + version_comparator: None, + executable_path: None, + target: None, + endpoints: None, + headers: Default::default(), + timeout: None, + installer_args: None, } } @@ -109,24 +121,25 @@ impl UpdaterBuilder { mut self, f: F, ) -> Self { - self.updater.version_comparator = Some(Box::new(f)); + self.version_comparator = Some(Box::new(f)); self } pub fn target(mut self, target: impl Into) -> Self { - self.target = Some(target.into()); + self.target.replace(target.into()); self } pub fn endpoints(mut self, endpoints: Vec) -> Self { - self.updater.endpoints = endpoints; + self.endpoints.replace(endpoints); self } pub fn executable_path>(mut self, p: P) -> Self { - self.executable_path = Some(PathBuf::from(p.as_ref())); + self.executable_path.replace(p.as_ref().into()); self } + pub fn header(mut self, key: K, value: V) -> Result where HeaderName: TryFrom, @@ -137,17 +150,13 @@ impl UpdaterBuilder { let key: std::result::Result = key.try_into().map_err(Into::into); let value: std::result::Result = value.try_into().map_err(Into::into); - self.updater.headers_map.insert(key?, value?); + self.headers.insert(key?, value?); + Ok(self) } pub fn timeout(mut self, timeout: Duration) -> Self { - self.updater.timeout = Some(timeout); - self - } - - pub fn app_image_path>(mut self, p: P) -> Self { - self.app_image_path = Some(PathBuf::from(p.as_ref())); + self.timeout = Some(timeout); self } @@ -156,71 +165,74 @@ impl UpdaterBuilder { I: IntoIterator, S: Into, { - self.updater.config.installer_args = args.into_iter().map(Into::into).collect(); + self.installer_args + .replace(args.into_iter().map(Into::into).collect()); self } - pub fn build(mut self) -> Result { - if self.updater.endpoints.is_empty() { + pub fn build(self) -> Result { + let endpoints = self + .endpoints + .unwrap_or_else(|| self.config.endpoints.into_iter().map(|e| e.0).collect()); + + if endpoints.is_empty() { return Err(Error::EmptyEndpoints); }; - let executable_path = self.executable_path.clone().unwrap_or(current_exe()?); - let arch = get_updater_arch().ok_or(Error::UnsupportedArch)?; - - // `target` is the `{{target}}` variable we replace in the endpoint - // `json_target` is the value we search if the updater server returns a JSON with the `platforms` object - (self.updater.target, self.updater.json_target) = match self.target { - Some(target) => (target.clone(), target), - None => { - let target = get_updater_target().ok_or(Error::UnsupportedOs)?; - (target.to_string(), format!("{target}-{arch}")) - } + let (target, json_target) = if let Some(target) = self.target { + (target.clone(), target) + } else { + let target = get_updater_target().ok_or(Error::UnsupportedOs)?; + (target.to_string(), format!("{target}-{arch}")) }; + let executable_path = self.executable_path.clone().unwrap_or(current_exe()?); + // Get the extract_path from the provided executable_path - self.updater.extract_path = - extract_path_from_executable(&executable_path, self.app_image_path)?; + let extract_path = if cfg!(target_os = "linux") { + executable_path + } else { + extract_path_from_executable(&executable_path)? + }; - Ok(self.updater) + Ok(Updater { + config: self.updater_config, + current_version: self.current_version, + version_comparator: self.version_comparator, + timeout: self.timeout, + endpoints, + installer_args: self.installer_args.unwrap_or(self.config.installer_args), + arch, + target, + json_target, + headers: self.headers, + extract_path, + }) } } pub struct Updater { + config: UpdaterConfig, current_version: Version, version_comparator: Option bool + Send + Sync>>, timeout: Option, endpoints: Vec, - arch: String, + #[allow(dead_code)] + installer_args: Vec, + arch: &'static str, + // The `{{target}}` variable we replace in the endpoint target: String, + // The value we search if the updater server returns a JSON with the `platforms` object json_target: String, - headers_map: HeaderMap, + headers: HeaderMap, extract_path: PathBuf, - config: crate::Config, - updater_config: UpdaterConfig, } impl Updater { - fn new(current_version: Version, config: crate::Config, updater_config: UpdaterConfig) -> Self { - Self { - current_version, - version_comparator: Default::default(), - timeout: Default::default(), - endpoints: Default::default(), - arch: Default::default(), - target: Default::default(), - headers_map: Default::default(), - extract_path: Default::default(), - json_target: Default::default(), - config, - updater_config, - } - } - pub async fn check(&self) -> Result> { // we want JSON only - let mut headers = self.headers_map.clone(); + let mut headers = self.headers.clone(); headers.insert("Accept", HeaderValue::from_str("application/json").unwrap()); // Set SSL certs for linux if they aren't available. @@ -248,7 +260,7 @@ impl Updater { .to_string() .replace("{{current_version}}", &self.current_version.to_string()) .replace("{{target}}", &self.target) - .replace("{{arch}}", &self.arch) + .replace("{{arch}}", self.arch) .parse()?; let mut request = Client::new().get(url).headers(headers.clone()); @@ -295,9 +307,8 @@ impl Updater { let update = if should_update { Some(Update { - config: self.config.clone(), current_version: self.current_version.to_string(), - updater_config: self.updater_config.clone(), + config: self.config.clone(), target: self.target.clone(), extract_path: self.extract_path.clone(), version: release.version.to_string(), @@ -306,7 +317,7 @@ impl Updater { body: release.notes.clone(), signature: release.signature(&self.json_target)?.to_owned(), timeout: self.timeout, - headers: self.headers_map.clone(), + headers: self.headers.clone(), }) } else { None @@ -318,9 +329,7 @@ impl Updater { #[derive(Debug, Clone)] pub struct Update { - #[allow(unused)] - config: crate::Config, - updater_config: UpdaterConfig, + config: UpdaterConfig, /// Update description pub body: Option, /// Version used to check for update @@ -399,11 +408,7 @@ impl Update { let mut update_buffer = Cursor::new(&buffer); - verify_signature( - &mut update_buffer, - &self.signature, - &self.updater_config.pubkey, - )?; + verify_signature(&mut update_buffer, &self.signature, &self.config.pubkey)?; Ok(buffer) } @@ -475,8 +480,8 @@ impl Update { if found_path.extension() == Some(OsStr::new("exe")) { // Run the EXE Command::new(found_path) - .args(self.updater_config.windows.install_mode.nsis_args()) - .args(&self.config.installer_args) + .args(self.config.windows.install_mode.nsis_args()) + .args(&self.installer_args) .spawn() .expect("installer failed to start"); @@ -494,7 +499,7 @@ impl Update { msi_path_arg.push("\"\"\""); let msiexec_args = self - .updater_config + .config .windows .install_mode .msiexec_args() @@ -595,7 +600,7 @@ impl Update { // extract the buffer to the tmp_dir // we extract our signed archive into our final directory without any temp file - let mut archive = tar::Archive::new(archive.clone()); + let mut archive = tar::Archive::new(archive); for mut entry in archive.entries()?.flatten() { if let Ok(path) = entry.path() { if path.extension() == Some(OsStr::new("AppImage")) { @@ -609,6 +614,8 @@ impl Update { } } } + + return Ok(()); } } } @@ -707,10 +714,7 @@ pub(crate) fn get_updater_arch() -> Option<&'static str> { } } -pub fn extract_path_from_executable( - executable_path: &Path, - _app_image_path: Option, -) -> Result { +pub fn extract_path_from_executable(executable_path: &Path) -> Result { // Return the path of the current executable by default // Example C:\Program Files\My App\ let extract_path = executable_path @@ -737,13 +741,6 @@ pub fn extract_path_from_executable( .ok_or(Error::FailedToDetermineExtractPath); } - // We should use APPIMAGE exposed env variable - // This is where our APPIMAGE should sit and should be replaced - #[cfg(target_os = "linux")] - if let Some(app_image_path) = _app_image_path { - return Ok(app_image_path); - } - Ok(extract_path) } diff --git a/plugins/updater/tests/app-updater/tests/update.rs b/plugins/updater/tests/app-updater/tests/update.rs index 6cc2033b..d6be2508 100644 --- a/plugins/updater/tests/app-updater/tests/update.rs +++ b/plugins/updater/tests/app-updater/tests/update.rs @@ -115,7 +115,7 @@ impl Default for BundleTarget { #[cfg(any(target_os = "macos", target_os = "ios"))] return Self::App; #[cfg(target_os = "linux")] - return Self::App; + return Self::AppImage; #[cfg(windows)] return Self::Nsis; }