From 086eb0a980aae109b4ed1dbfc566eee2959f5f4e Mon Sep 17 00:00:00 2001 From: Caelan Sayler Date: Thu, 8 Aug 2024 20:23:51 +0100 Subject: [PATCH] wip --- .gitignore | 10 +++ Cargo.lock | 57 +++++++++++++++ Cargo.toml | 1 + src/lib-node/.gitignore | 8 --- src/lib-node/Cargo.toml | 3 - .../{veloz => velopack_nodeffi}/Cargo.toml | 5 +- .../crates/velopack_nodeffi/src/lib.rs | 49 +++++++++++++ src/lib-node/crates/veloz/src/lib.rs | 11 --- src/lib-rust/src/manager.rs | 71 ++++++++----------- src/lib-rust/src/sources.rs | 32 +++++---- 10 files changed, 169 insertions(+), 78 deletions(-) delete mode 100644 src/lib-node/.gitignore delete mode 100644 src/lib-node/Cargo.toml rename src/lib-node/crates/{veloz => velopack_nodeffi}/Cargo.toml (72%) create mode 100644 src/lib-node/crates/velopack_nodeffi/src/lib.rs delete mode 100644 src/lib-node/crates/veloz/src/lib.rs diff --git a/.gitignore b/.gitignore index 70635906..bbbd7cf2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,16 @@ target/ _docyml/ +target +index.node +**/node_modules +**/.DS_Store +npm-debug.log* +lib +cargo.log +cross.log + + ################# ## Eclipse ################# diff --git a/Cargo.lock b/Cargo.lock index cd5bf9e7..fbfb5cc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1207,6 +1207,32 @@ dependencies = [ "tempfile", ] +[[package]] +name = "neon" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d75440242411c87dc39847b0e33e961ec1f10326a9d8ecf9c1ea64a3b3c13dc" +dependencies = [ + "getrandom", + "libloading", + "neon-macros", + "once_cell", + "semver", + "send_wrapper", + "smallvec", +] + +[[package]] +name = "neon-macros" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6813fde79b646e47e7ad75f480aa80ef76a5d9599e2717407961531169ee38b" +dependencies = [ + "quote", + "syn 2.0.72", + "syn-mid", +] + [[package]] name = "nix" version = "0.26.4" @@ -1718,6 +1744,12 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.204" @@ -1791,6 +1823,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "socket2" version = "0.4.10" @@ -1857,6 +1895,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn-mid" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5dc35bb08dd1ca3dfb09dce91fd2d13294d6711c88897d9a9d60acf39bce049" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "tempfile" version = "3.12.0" @@ -2139,6 +2188,14 @@ dependencies = [ "zstd", ] +[[package]] +name = "velopack_nodeffi" +version = "0.1.0" +dependencies = [ + "neon", + "velopack", +] + [[package]] name = "versions" version = "5.0.1" diff --git a/Cargo.toml b/Cargo.toml index 88a97491..b5e6ad93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ resolver = "2" members = [ "src/bins", "src/lib-rust", + "src/lib-node/crates/velopack_nodeffi", # "src/lib-cpp/generator" ] diff --git a/src/lib-node/.gitignore b/src/lib-node/.gitignore deleted file mode 100644 index 8ec40c75..00000000 --- a/src/lib-node/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -target -index.node -**/node_modules -**/.DS_Store -npm-debug.log* -lib -cargo.log -cross.log diff --git a/src/lib-node/Cargo.toml b/src/lib-node/Cargo.toml deleted file mode 100644 index 53f6dbf3..00000000 --- a/src/lib-node/Cargo.toml +++ /dev/null @@ -1,3 +0,0 @@ -[workspace] -members = ["crates/veloz"] -resolver = "2" diff --git a/src/lib-node/crates/veloz/Cargo.toml b/src/lib-node/crates/velopack_nodeffi/Cargo.toml similarity index 72% rename from src/lib-node/crates/veloz/Cargo.toml rename to src/lib-node/crates/velopack_nodeffi/Cargo.toml index 045edbe7..3c8527b5 100644 --- a/src/lib-node/crates/veloz/Cargo.toml +++ b/src/lib-node/crates/velopack_nodeffi/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "veloz" +name = "velopack_nodeffi" version = "0.1.0" -license = "ISC" +license = "MIT" edition = "2021" exclude = ["index.node"] @@ -12,3 +12,4 @@ crate-type = ["cdylib"] [dependencies] neon = "1" +velopack = { path = "../../../lib-rust" } diff --git a/src/lib-node/crates/velopack_nodeffi/src/lib.rs b/src/lib-node/crates/velopack_nodeffi/src/lib.rs new file mode 100644 index 00000000..e4372279 --- /dev/null +++ b/src/lib-node/crates/velopack_nodeffi/src/lib.rs @@ -0,0 +1,49 @@ +use neon::prelude::*; +use velopack::*; +use velopack::sources::*; + + +struct UpdateManagerWrapper<'a> { + manager: UpdateManager<'a>, +} + +impl<'a> Finalize for UpdateManagerWrapper<'a> {} + + +fn get_js_options(mut cx: FunctionContext, obj: &Handle) -> JsResult { + let allow_downgrade = obj.get(&mut cx, "allowDowngrade")?; + +} + +fn js_new_from_http_source(mut cx: FunctionContext) -> JsResult> { + let url = cx.argument::(0)?.value(&mut cx); + + let options: Option = None; + + + let obj = cx.argument::(1)?; + + + + + + + + let source = HttpSource::new(&url); + let um = UpdateManager::new(source, options).map_err(|e| cx.throw_error(e.to_string()))?; + + let wrapper = UpdateManagerWrapper { manager: um }; + + + Ok(cx.boxed(wrapper)) +} + +fn hello(mut cx: FunctionContext) -> JsResult { + Ok(cx.string("hello node")) +} + +#[neon::main] +fn main(mut cx: ModuleContext) -> NeonResult<()> { + cx.export_function("hello", hello)?; + Ok(()) +} diff --git a/src/lib-node/crates/veloz/src/lib.rs b/src/lib-node/crates/veloz/src/lib.rs deleted file mode 100644 index 9fd52d67..00000000 --- a/src/lib-node/crates/veloz/src/lib.rs +++ /dev/null @@ -1,11 +0,0 @@ -use neon::prelude::*; - -fn hello(mut cx: FunctionContext) -> JsResult { - Ok(cx.string("hello node")) -} - -#[neon::main] -fn main(mut cx: ModuleContext) -> NeonResult<()> { - cx.export_function("hello", hello)?; - Ok(()) -} diff --git a/src/lib-rust/src/manager.rs b/src/lib-rust/src/manager.rs index 5db3c4da..1e457fa0 100644 --- a/src/lib-rust/src/manager.rs +++ b/src/lib-rust/src/manager.rs @@ -1,4 +1,4 @@ -use std::{fs, process::Command as Process, process::exit}; +use std::{fs, process::{exit, Command as Process}, rc::Rc, sync::mpsc::Sender}; #[cfg(target_os = "windows")] use std::os::windows::process::CommandExt; @@ -91,26 +91,24 @@ pub struct UpdateOptions { } /// Provides functionality for checking for updates, downloading updates, and applying updates to the current application. -pub struct UpdateManager - where - T: UpdateSource, +pub struct UpdateManager<'a> { allow_version_downgrade: bool, explicit_channel: Option, - source: T, + source: Rc>, paths: VelopackLocator, } -impl Clone for UpdateManager { - fn clone(&self) -> Self { - UpdateManager { - allow_version_downgrade: self.allow_version_downgrade, - explicit_channel: self.explicit_channel.clone(), - source: self.source.clone(), - paths: self.paths.clone(), - } - } -} +// impl Clone for UpdateManager { +// fn clone(&self) -> Self { +// UpdateManager { +// allow_version_downgrade: self.allow_version_downgrade, +// explicit_channel: self.explicit_channel.clone(), +// source: self.source.clone(), +// paths: self.paths.clone(), +// } +// } +// } /// Arguments to pass to the Update.exe process when restarting the application after applying updates. pub enum RestartArgs<'a> { @@ -145,7 +143,7 @@ pub enum UpdateCheck { UpdateAvailable(UpdateInfo), } -impl UpdateManager { +impl<'a> UpdateManager<'a> { /// Create a new UpdateManager instance using the specified UpdateSource. /// This will return an error if the application is not yet installed. /// ## Example: @@ -155,12 +153,12 @@ impl UpdateManager { /// let source = sources::HttpSource::new("https://the.place/you-host/updates"); /// let um = UpdateManager::new(source, None); /// ``` - pub fn new(source: T, options: Option) -> Result, Error> { + pub fn new(source: T, options: Option) -> Result, Error> { Ok(UpdateManager { paths: locator::auto_locate()?, allow_version_downgrade: options.as_ref().map(|f| f.AllowVersionDowngrade).unwrap_or(false), explicit_channel: options.as_ref().map(|f| f.ExplicitChannel.clone()).unwrap_or(None), - source, + source: Rc::new(Box::new(source)), }) } @@ -232,7 +230,6 @@ impl UpdateManager { debug!("Latest remote release: {} ({}).", remote_asset.FileName, remote_version.to_string()); - if remote_version > app.version { info!("Found newer remote release available ({} -> {}).", app.version, remote_version); Ok(UpdateCheck::UpdateAvailable(UpdateInfo { TargetFullRelease: remote_asset, IsDowngrade: false })) @@ -260,13 +257,13 @@ impl UpdateManager { async_std::task::spawn_blocking(move || self_clone.check_for_updates()) } - /// Downloads the specified updates to the local app packages directory. If the update contains delta packages and the delta feature is enabled - /// this method will attempt to unpack and prepare them. If there is no delta update available, or there is an error preparing delta - /// packages, this method will fall back to downloading the full version of the update. This function will acquire a global update lock - /// so may fail if there is already another update operation in progress. - pub fn download_updates(&self, update: &UpdateInfo, progress: A) -> Result<(), Error> - where - A: FnMut(i16), + /// Downloads the specified updates to the local app packages directory. Progress is reported back to the caller via an optional Sender. + /// This function will acquire a global update lock so may fail if there is already another update operation in progress. + /// - If the update contains delta packages and the delta feature is enabled + /// this method will attempt to unpack and prepare them. + /// - If there is no delta update available, or there is an error preparing delta + /// packages, this method will fall back to downloading the full version of the update. + pub fn download_updates(&self, update: &UpdateInfo, progress: Option>) -> Result<(), Error> { let name = &update.TargetFullRelease.FileName; let packages_dir = &self.paths.packages_dir; @@ -321,25 +318,17 @@ impl UpdateManager { } #[cfg(feature = "async")] - /// Downloads the specified updates to the local app packages directory. If the update contains delta packages and the delta feature is enabled - /// this method will attempt to unpack and prepare them. If there is no delta update available, or there is an error preparing delta - /// packages, this method will fall back to downloading the full version of the update. This function will acquire a global update lock - /// so may fail if there is already another update operation in progress. + /// Downloads the specified updates to the local app packages directory. Progress is reported back to the caller via an optional Sender. + /// This function will acquire a global update lock so may fail if there is already another update operation in progress. + /// - If the update contains delta packages and the delta feature is enabled + /// this method will attempt to unpack and prepare them. + /// - If there is no delta update available, or there is an error preparing delta + /// packages, this method will fall back to downloading the full version of the update. pub fn download_updates_async(&self, update: &UpdateInfo, progress: Option>) -> JoinHandle> - where - T: 'static, { let self_clone = self.clone(); let update_clone = update.clone(); - if let Some(p) = progress { - async_std::task::spawn_blocking(move || { - self_clone.download_updates(&update_clone, move |x| { - let _ = p.try_send(x); - }) - }) - } else { - async_std::task::spawn_blocking(move || self_clone.download_updates(&update_clone, |_| {})) - } + async_std::task::spawn_blocking(move || self_clone.download_updates(&update_clone, progress)) } /// This will exit your app immediately, apply updates, and then optionally relaunch the app using the specified diff --git a/src/lib-rust/src/sources.rs b/src/lib-rust/src/sources.rs index 402d7149..451efccf 100644 --- a/src/lib-rust/src/sources.rs +++ b/src/lib-rust/src/sources.rs @@ -1,17 +1,19 @@ -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, + sync::mpsc::Sender, +}; use crate::*; /// Abstraction for finding and downloading updates from a package source / repository. /// An implementation may copy a file from a local repository, download from a web address, /// or even use third party services and parse proprietary data to produce a package feed. -pub trait UpdateSource: Clone + Send + Sync { +pub trait UpdateSource: Send + Sync { /// Retrieve the list of available remote releases from the package source. These releases /// can subsequently be downloaded with download_release_entry. fn get_release_feed(&self, channel: &str, app: &manifest::Manifest) -> Result; /// Download the specified VelopackAsset to the provided local file path. - fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, progress: A) -> Result<(), Error> - where A: FnMut(i16); + fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, progress_sender: Option>) -> Result<(), Error>; } #[derive(Clone)] @@ -44,15 +46,17 @@ impl UpdateSource for HttpSource { Ok(feed) } - fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, progress: A) -> Result<(), Error> - where A: FnMut(i16), - { + fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, progress_sender: Option>) -> Result<(), Error> { let path = self.url.trim_end_matches('/').to_owned() + "/"; let url = url::Url::parse(&path)?; let asset_url = url.join(&asset.FileName)?; info!("About to download from URL '{}' to file '{}'", asset_url, local_file); - download::download_url_to_file(asset_url.as_str(), local_file, progress)?; + download::download_url_to_file(asset_url.as_str(), local_file, move |p| { + if let Some(progress_sender) = &progress_sender { + let _ = progress_sender.send(p); + } + })?; Ok(()) } } @@ -83,14 +87,16 @@ impl UpdateSource for FileSource { Ok(feed) } - fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, mut progress: A) -> Result<(), Error> - where A: FnMut(i16), - { + fn download_release_entry(&self, asset: &VelopackAsset, local_file: &str, progress_sender: Option>) -> Result<(), Error> { let asset_path = self.path.join(&asset.FileName); info!("About to copy from file '{}' to file '{}'", asset_path.display(), local_file); - progress(50); + if let Some(progress_sender) = &progress_sender { + let _ = progress_sender.send(50); + } std::fs::copy(asset_path, local_file)?; - progress(100); + if let Some(progress_sender) = &progress_sender { + let _ = progress_sender.send(100); + } Ok(()) } }