mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
add more rust/node functions
This commit is contained in:
84
Cargo.lock
generated
84
Cargo.lock
generated
@@ -269,6 +269,15 @@ version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.6.1"
|
||||
@@ -474,6 +483,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
@@ -489,6 +507,16 @@ version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cvt"
|
||||
version = "0.1.2"
|
||||
@@ -545,6 +573,16 @@ version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "2.0.2"
|
||||
@@ -807,6 +845,16 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
@@ -1677,12 +1725,34 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1_smol"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
@@ -1963,6 +2033,12 @@ dependencies = [
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.15"
|
||||
@@ -2044,6 +2120,8 @@ dependencies = [
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1",
|
||||
"sha2",
|
||||
"thiserror",
|
||||
"ts-rs",
|
||||
"ureq",
|
||||
@@ -2114,6 +2192,12 @@ dependencies = [
|
||||
"velopack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "versions"
|
||||
version = "5.0.1"
|
||||
|
||||
@@ -55,6 +55,8 @@ file-rotate = "0.7"
|
||||
simple-stopwatch = "0.1"
|
||||
enum-flags = "0.3"
|
||||
remove_dir_all = { git = "https://github.com/caesay/remove_dir_all.git", features = ["log"] }
|
||||
sha1 = "0.10"
|
||||
sha2 = "0.10"
|
||||
sha1_smol = "1.0"
|
||||
time = "0.3"
|
||||
os_info = "3.8"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { app, BrowserWindow, ipcMain } from 'electron';
|
||||
import { app, BrowserWindow } from 'electron';
|
||||
import { VelopackApp } from "velopack";
|
||||
import { initializeUpdates } from "./update"
|
||||
// This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack
|
||||
@@ -13,7 +13,7 @@ VelopackApp.build()
|
||||
.setLogger((lvl, msg) => console.log(`Velopack [${lvl}] ${msg}`))
|
||||
.run();
|
||||
|
||||
// configure IPC listener for update messages
|
||||
// Configure IPC listener for Velopack update messages
|
||||
initializeUpdates();
|
||||
|
||||
const createWindow = (): void => {
|
||||
@@ -48,11 +48,6 @@ app.on('window-all-closed', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Respond to quit messages from the render
|
||||
ipcMain.on("exit-request", () => {
|
||||
app.quit();
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
// On OS X it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
|
||||
@@ -52,7 +52,6 @@ strum.workspace = true
|
||||
derivative.workspace = true
|
||||
glob.workspace = true
|
||||
remove_dir_all.workspace = true
|
||||
sha1_smol.workspace = true
|
||||
time.workspace = true
|
||||
os_info.workspace = true
|
||||
bitflags.workspace = true
|
||||
@@ -111,6 +110,7 @@ filelocksmith.workspace = true
|
||||
tempfile.workspace = true
|
||||
ntest.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
sha1_smol.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
semver.workspace = true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::shared::{self, OperationWait};
|
||||
use velopack::{locator::VelopackLocator, constants};
|
||||
use velopack::{locator, locator::VelopackLocator, constants};
|
||||
use anyhow::{bail, Result};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn apply<'a>(
|
||||
shared::operation_wait(wait);
|
||||
|
||||
let packages_dir = locator.get_packages_dir();
|
||||
let package = package.cloned().or_else(|| shared::find_latest_full_package(&packages_dir).map(|x| x.0));
|
||||
let package = package.cloned().or_else(|| locator::find_latest_full_package(&packages_dir).map(|x| x.0));
|
||||
|
||||
match package {
|
||||
Some(package) => {
|
||||
|
||||
@@ -12,7 +12,7 @@ use std::{
|
||||
process::Command as Process,
|
||||
};
|
||||
use velopack::{bundle::Manifest, constants};
|
||||
use velopack::locator::{auto_locate_app_manifest, create_config_from_root_dir, LocationContext, VelopackLocator};
|
||||
use velopack::locator::{self, LocationContext, VelopackLocator};
|
||||
use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow;
|
||||
|
||||
enum LocatorResult
|
||||
@@ -62,7 +62,7 @@ impl LocatorResult {
|
||||
}
|
||||
|
||||
fn legacy_locator() -> Result<LocatorResult> {
|
||||
let locator = auto_locate_app_manifest(LocationContext::IAmUpdateExe);
|
||||
let locator = locator::auto_locate_app_manifest(LocationContext::IAmUpdateExe);
|
||||
match locator {
|
||||
Ok(locator) => Ok(LocatorResult::Normal(locator)),
|
||||
Err(e) => {
|
||||
@@ -70,7 +70,7 @@ fn legacy_locator() -> Result<LocatorResult> {
|
||||
let my_exe = std::env::current_exe()?;
|
||||
let parent_dir = my_exe.parent().expect("Unable to determine parent directory");
|
||||
let packages_dir = parent_dir.join("packages");
|
||||
if let Some((path, manifest)) = shared::find_latest_full_package(&packages_dir) {
|
||||
if let Some((path, manifest)) = locator::find_latest_full_package(&packages_dir) {
|
||||
info!("Found full package to read: {}", path.to_string_lossy());
|
||||
Ok(LocatorResult::Legacy(parent_dir.to_path_buf(), manifest))
|
||||
} else {
|
||||
@@ -148,9 +148,9 @@ fn try_legacy_migration(root_dir: &PathBuf, manifest: &Manifest) -> Result<Velop
|
||||
std::env::set_current_dir(&root_dir)?;
|
||||
|
||||
let _mutex = shared::retry_io(|| crate::windows::create_global_mutex(&manifest.id))?;
|
||||
let path_config = create_config_from_root_dir(root_dir);
|
||||
let path_config = locator::create_config_from_root_dir(root_dir);
|
||||
|
||||
let package = shared::find_latest_full_package(&path_config.PackagesDir).ok_or_else(|| anyhow!("Unable to find latest full package."))?;
|
||||
let package = locator::find_latest_full_package(&path_config.PackagesDir).ok_or_else(|| anyhow!("Unable to find latest full package."))?;
|
||||
|
||||
warn!("This application is installed in a folder prefixed with 'app-'. Attempting to migrate...");
|
||||
let _ = shared::force_stop_package(&root_dir);
|
||||
|
||||
@@ -2,8 +2,6 @@ use anyhow::{anyhow, Result};
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use regex::Regex;
|
||||
use std::{path::Path, thread, time::Duration};
|
||||
use std::path::PathBuf;
|
||||
use velopack::bundle::{load_bundle_from_file, Manifest};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum OperationWait {
|
||||
@@ -26,30 +24,6 @@ pub fn operation_wait(wait: OperationWait) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_latest_full_package(packages_dir: &PathBuf) -> Option<(PathBuf, Manifest)> {
|
||||
let packages_dir = packages_dir.to_string_lossy();
|
||||
|
||||
info!("Attempting to auto-detect package in: {}", packages_dir);
|
||||
let mut package: Option<(PathBuf, Manifest)> = None;
|
||||
|
||||
if let Ok(paths) = glob::glob(format!("{}/*.nupkg", packages_dir).as_str()) {
|
||||
for path in paths {
|
||||
if let Ok(path) = path {
|
||||
trace!("Checking package: '{}'", path.to_string_lossy());
|
||||
if let Ok(mut bun) = load_bundle_from_file(&path) {
|
||||
if let Ok(mani) = bun.read_manifest() {
|
||||
if package.is_none() || mani.version > package.clone().unwrap().1.version {
|
||||
info!("Found {}: '{}'", mani.version, path.to_string_lossy());
|
||||
package = Some((path, mani));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package
|
||||
}
|
||||
|
||||
pub fn retry_io<F, T, E>(op: F) -> Result<T, E>
|
||||
where
|
||||
F: Fn() -> Result<T, E>,
|
||||
|
||||
@@ -15,10 +15,11 @@ declare module "./load" {
|
||||
|
||||
function js_get_current_version(um: UpdateManagerOpaque): string;
|
||||
|
||||
// function js_get_app_id(um: UpdateManagerOpaque): string;
|
||||
// function js_is_portable(um: UpdateManagerOpaque): boolean;
|
||||
// function js_is_installed(um: UpdateManagerOpaque): boolean;
|
||||
// function js_is_update_pending_restart(um: UpdateManagerOpaque): boolean;
|
||||
function js_get_app_id(um: UpdateManagerOpaque): string;
|
||||
|
||||
function js_is_portable(um: UpdateManagerOpaque): boolean;
|
||||
|
||||
function js_update_pending_restart(um: UpdateManagerOpaque): UpdateInfo | null;
|
||||
|
||||
function js_check_for_updates_async(
|
||||
um: UpdateManagerOpaque,
|
||||
@@ -146,14 +147,6 @@ export class VelopackApp {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom logger callback to receive log messages from Velopack. The default behavior is to log to console.log.
|
||||
*/
|
||||
setLogger(callback: (loglevel: LogLevel, msg: string) => void): VelopackApp {
|
||||
addon.js_set_logger_callback(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the Velopack startup logic. This should be the first thing to run in your app.
|
||||
* In some circumstances it may terminate/restart the process to perform tasks.
|
||||
@@ -194,21 +187,28 @@ export class UpdateManager {
|
||||
return addon.js_get_current_version(this.opaque);
|
||||
}
|
||||
|
||||
// getAppId(): string {
|
||||
// return addon.js_get_app_id.call(this.opaque);
|
||||
// }
|
||||
/**
|
||||
* Returns the currently installed app id.
|
||||
*/
|
||||
getAppId(): string {
|
||||
return addon.js_get_app_id.call(this.opaque);
|
||||
}
|
||||
|
||||
// isInstalled(): boolean {
|
||||
// return addon.js_is_installed.call(this.opaque);
|
||||
// }
|
||||
/**
|
||||
* Returns whether the app is in portable mode. On Windows this can be true or false.
|
||||
* On MacOS and Linux this will always be true.
|
||||
*/
|
||||
isPortable(): boolean {
|
||||
return addon.js_is_portable.call(this.opaque);
|
||||
}
|
||||
|
||||
// isPortable(): boolean {
|
||||
// return addon.js_is_portable.call(this.opaque);
|
||||
// }
|
||||
|
||||
// isUpdatePendingRestart(): boolean {
|
||||
// return addon.js_is_update_pending_restart.call(this.opaque);
|
||||
// }
|
||||
/**
|
||||
* Returns an UpdateInfo object if there is an update downloaded which still needs to be applied.
|
||||
* You can pass the UpdateInfo object to waitExitThenApplyUpdate to apply the update.
|
||||
*/
|
||||
getUpdatePendingRestart(): UpdateInfo | null {
|
||||
return addon.js_update_pending_restart.call(this.opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for updates, returning None if there are none available. If there are updates available, this method will return an
|
||||
@@ -271,3 +271,10 @@ export class UpdateManager {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom logger callback to receive log messages from Velopack. The default behavior is to log to console.log.
|
||||
*/
|
||||
export function setVelopackLogger(callback: (loglevel: LogLevel, msg: string) => void) {
|
||||
addon.js_set_logger_callback(callback);
|
||||
}
|
||||
@@ -68,10 +68,41 @@ fn js_new_update_manager(mut cx: FunctionContext) -> JsResult<BoxedUpdateManager
|
||||
fn js_get_current_version(mut cx: FunctionContext) -> JsResult<JsString> {
|
||||
let mgr_boxed = cx.argument::<BoxedUpdateManager>(0)?;
|
||||
let mgr_ref = &mgr_boxed.borrow().manager;
|
||||
let version = mgr_ref.current_version().or_else(|e| cx.throw_error(e.to_string()))?;
|
||||
let version = mgr_ref.get_current_version();
|
||||
Ok(cx.string(version))
|
||||
}
|
||||
|
||||
fn js_get_app_id(mut cx: FunctionContext) -> JsResult<JsString> {
|
||||
let mgr_boxed = cx.argument::<BoxedUpdateManager>(0)?;
|
||||
let mgr_ref = &mgr_boxed.borrow().manager;
|
||||
let id = mgr_ref.get_app_id();
|
||||
Ok(cx.string(id))
|
||||
}
|
||||
|
||||
fn js_is_portable(mut cx: FunctionContext) -> JsResult<JsBoolean> {
|
||||
let mgr_boxed = cx.argument::<BoxedUpdateManager>(0)?;
|
||||
let mgr_ref = &mgr_boxed.borrow().manager;
|
||||
let is_portable = mgr_ref.get_is_portable();
|
||||
Ok(cx.boolean(is_portable))
|
||||
}
|
||||
|
||||
fn js_update_pending_restart(mut cx: FunctionContext) -> JsResult<JsValue> {
|
||||
let mgr_boxed = cx.argument::<BoxedUpdateManager>(0)?;
|
||||
let mgr_ref = &mgr_boxed.borrow().manager;
|
||||
let pending_restart = mgr_ref.get_update_pending_restart();
|
||||
|
||||
if let Some(asset) = pending_restart {
|
||||
let json = serde_json::to_string(&asset);
|
||||
match json {
|
||||
Ok(json) => Ok(cx.string(json).upcast()),
|
||||
Err(e) => cx.throw_error(e.to_string()),
|
||||
}
|
||||
} else {
|
||||
let nil = cx.null().upcast();
|
||||
Ok(nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn js_check_for_updates_async(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
||||
let mgr_boxed = cx.argument::<BoxedUpdateManager>(0)?;
|
||||
let mgr_ref = &mgr_boxed.borrow().manager;
|
||||
@@ -254,10 +285,9 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
||||
|
||||
cx.export_function("js_new_update_manager", js_new_update_manager)?;
|
||||
cx.export_function("js_get_current_version", js_get_current_version)?;
|
||||
// cx.export_function("js_get_app_id", js_get_app_id)?;
|
||||
// cx.export_function("js_is_portable", js_is_portable)?;
|
||||
// cx.export_function("js_is_installed", js_is_installed)?;
|
||||
// cx.export_function("js_is_update_pending_restart", js_is_update_pending_restart)?;
|
||||
cx.export_function("js_get_app_id", js_get_app_id)?;
|
||||
cx.export_function("js_is_portable", js_is_portable)?;
|
||||
cx.export_function("js_update_pending_restart", js_update_pending_restart)?;
|
||||
cx.export_function("js_check_for_updates_async", js_check_for_updates_async)?;
|
||||
cx.export_function("js_download_update_async", js_download_update_async)?;
|
||||
cx.export_function("js_wait_exit_then_apply_update", js_wait_exit_then_apply_update)?;
|
||||
|
||||
@@ -44,6 +44,8 @@ normpath.workspace = true
|
||||
bitflags.workspace = true
|
||||
rand.workspace = true
|
||||
native-tls.workspace = true
|
||||
sha1.workspace = true
|
||||
sha2.workspace = true
|
||||
|
||||
# typescript
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
|
||||
@@ -355,6 +355,8 @@ pub struct Manifest {
|
||||
pub channel: String,
|
||||
pub shortcut_locations: String,
|
||||
pub shortcut_amuid: String,
|
||||
pub release_notes: String,
|
||||
pub release_notes_html: String,
|
||||
}
|
||||
|
||||
/// Parse manifest object from an XML string.
|
||||
@@ -399,6 +401,10 @@ pub fn read_manifest_from_string(xml: &str) -> Result<Manifest, Error> {
|
||||
obj.shortcut_locations = text;
|
||||
} else if el_name == "shortcutAmuid" {
|
||||
obj.shortcut_amuid = text;
|
||||
} else if el_name == "releaseNotes" {
|
||||
obj.release_notes = text;
|
||||
} else if el_name == "releaseNotesHtml" {
|
||||
obj.release_notes_html = text;
|
||||
}
|
||||
}
|
||||
Ok(XmlEvent::EndElement { .. }) => {
|
||||
|
||||
@@ -482,3 +482,27 @@ fn read_current_manifest(nuspec_path: &PathBuf) -> Result<Manifest, Error> {
|
||||
Err(Error::MissingNuspec)
|
||||
}
|
||||
|
||||
/// Returns the path and manifest of the latest full package in the given directory.
|
||||
pub fn find_latest_full_package(packages_dir: &PathBuf) -> Option<(PathBuf, Manifest)> {
|
||||
let packages_dir = packages_dir.to_string_lossy();
|
||||
|
||||
info!("Attempting to auto-detect package in: {}", packages_dir);
|
||||
let mut package: Option<(PathBuf, Manifest)> = None;
|
||||
|
||||
if let Ok(paths) = glob::glob(format!("{}/*.nupkg", packages_dir).as_str()) {
|
||||
for path in paths {
|
||||
if let Ok(path) = path {
|
||||
trace!("Checking package: '{}'", path.to_string_lossy());
|
||||
if let Ok(mut bun) = bundle::load_bundle_from_file(&path) {
|
||||
if let Ok(mani) = bun.read_manifest() {
|
||||
if package.is_none() || mani.version > package.clone().unwrap().1.version {
|
||||
info!("Found {}: '{}'", mani.version, path.to_string_lossy());
|
||||
package = Some((path, mani));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ use semver::Version;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
locator::{self, VelopackLocatorConfig},
|
||||
locator::{self, VelopackLocatorConfig, LocationContext, VelopackLocator},
|
||||
sources::UpdateSource,
|
||||
Error,
|
||||
util,
|
||||
};
|
||||
use crate::locator::{auto_locate_app_manifest, LocationContext, VelopackLocator};
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
|
||||
@@ -140,7 +140,7 @@ impl UpdateManager {
|
||||
let manifest = config.load_manifest()?;
|
||||
VelopackLocator::new(config.clone(), manifest)
|
||||
} else {
|
||||
auto_locate_app_manifest(LocationContext::FromCurrentExe)?
|
||||
locator::auto_locate_app_manifest(LocationContext::FromCurrentExe)?
|
||||
};
|
||||
Ok(UpdateManager {
|
||||
options: options.unwrap_or_default(),
|
||||
@@ -160,8 +160,42 @@ impl UpdateManager {
|
||||
}
|
||||
|
||||
/// The currently installed app version.
|
||||
pub fn current_version(&self) -> Result<String, Error> {
|
||||
Ok(self.locator.get_manifest_version_full_string())
|
||||
pub fn get_current_version(&self) -> String {
|
||||
self.locator.get_manifest_version_full_string()
|
||||
}
|
||||
|
||||
/// The currently installed app id.
|
||||
pub fn get_app_id(&self) -> String {
|
||||
self.locator.get_manifest_id()
|
||||
}
|
||||
|
||||
/// Check if the app is in portable mode. This can be true or false on Windows.
|
||||
/// On Linux and MacOS, this will always return true.
|
||||
pub fn get_is_portable(&self) -> bool {
|
||||
self.locator.get_is_portable()
|
||||
}
|
||||
|
||||
/// Returns None if there is no local package waiting to be applied. Returns a VelopackAsset
|
||||
/// if there is an update downloaded which has not yet been applied. In that case, the
|
||||
/// VelopackAsset can be applied by calling apply_updates_and_restart or wait_exit_then_apply_updates.
|
||||
pub fn get_update_pending_restart(&self) -> Option<VelopackAsset> {
|
||||
let packages_dir = self.locator.get_packages_dir();
|
||||
if let Some((path, manifest)) = locator::find_latest_full_package(&packages_dir) {
|
||||
if manifest.version > self.locator.get_manifest_version() {
|
||||
return Some(VelopackAsset {
|
||||
PackageId: manifest.id,
|
||||
Version: manifest.version.to_string(),
|
||||
Type: "Full".to_string(),
|
||||
FileName: path.file_name().unwrap().to_string_lossy().to_string(),
|
||||
SHA1: util::calculate_file_sha1(&path).unwrap_or_default(),
|
||||
SHA256: util::calculate_file_sha256(&path).unwrap_or_default(),
|
||||
Size: path.metadata().map(|m| m.len()).unwrap_or(0),
|
||||
NotesMarkdown: manifest.release_notes,
|
||||
NotesHtml: manifest.release_notes_html,
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Get a list of available remote releases from the package source.
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
use crate::Error;
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
use sha2::Digest;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use rand::distributions::{Alphanumeric, DistString};
|
||||
|
||||
pub fn retry_io<F, T, E>(op: F) -> Result<T, E>
|
||||
where
|
||||
@@ -37,3 +41,19 @@ where
|
||||
pub fn random_string(len: usize) -> String {
|
||||
Alphanumeric.sample_string(&mut rand::thread_rng(), len)
|
||||
}
|
||||
|
||||
pub fn calculate_file_sha256<P: AsRef<Path>>(file: P) -> Result<String, Error> {
|
||||
let mut file = File::open(file)?;
|
||||
let mut sha256 = sha2::Sha256::new();
|
||||
std::io::copy(&mut file, &mut sha256)?;
|
||||
let hash = sha256.finalize();
|
||||
Ok(format!("{:x}", hash))
|
||||
}
|
||||
|
||||
pub fn calculate_file_sha1<P: AsRef<Path>>(file: P) -> Result<String, Error> {
|
||||
let mut file = File::open(file)?;
|
||||
let mut sha1o = sha1::Sha1::new();
|
||||
std::io::copy(&mut file, &mut sha1o)?;
|
||||
let hash = sha1o.finalize();
|
||||
Ok(format!("{:x}", hash))
|
||||
}
|
||||
Reference in New Issue
Block a user