This commit is contained in:
Caelan Sayler
2024-10-16 22:47:02 +01:00
committed by Caelan
parent e3a7b4614a
commit 3694119869
4 changed files with 300 additions and 39 deletions

View File

@@ -91,13 +91,13 @@ typedef struct {
} vpkc_update_info_t;
// Update Manager
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, const vpkc_locator_t* locator, vpkc_update_manager_t* pManager);
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, vpkc_locator_t* pLocator, vpkc_update_manager_t* pManager);
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion);
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId);
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager);
VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset);
VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate);
VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, const vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress);
VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress);
VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs);
// VelopackApp
@@ -116,8 +116,8 @@ VPKC_EXPORT void VPKC_CALL vpkc_app_run();
VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError);
VPKC_EXPORT void VPKC_CALL vpkc_set_log(vpkc_log_callback_t cbLog);
VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager);
VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pManager);
VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pManager);
VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pUpdateInfo);
VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pAsset);
#ifdef __cplusplus
}

View File

@@ -1,14 +1,239 @@
#include "velopack_libc/src/lib.rs.h"
// Error handling
char* lastError;
LoggerCallbackManager logMgr{};
VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError) {
if (lastError == nullptr) {
return 0;
}
if (pszError == nullptr || cError == 0) {
return strlen(lastError);
}
size_t len = strlen(lastError);
if (len > cError) {
len = cError;
}
memcpy(pszError, lastError, len);
return len;
}
static inline void set_last_error(const char* pszError) {
if (lastError != nullptr) {
free(lastError);
}
lastError = _strdup(pszError);
}
static inline void clear_last_error() {
if (lastError != nullptr) {
free(lastError);
lastError = nullptr;
}
}
static inline void copy_to_locator_option(vpkc_locator_t* pLocator, LocatorConfigOption& locator) {
if (pLocator) {
locator.has_data = true;
locator.data.RootAppDir = pLocator->RootAppDir;
locator.data.UpdateExePath = pLocator->UpdateExePath;
locator.data.PackagesDir = pLocator->PackagesDir;
locator.data.ManifestPath = pLocator->ManifestPath;
locator.data.CurrentBinaryDir = pLocator->CurrentBinaryDir;
locator.data.IsPortable = pLocator->IsPortable;
} else {
locator.has_data = false;
}
}
static inline void copy_to_asset_dto(vpkc_asset_t* pAsset, AssetDto& asset) {
if (pAsset != nullptr) {
asset.PackageId = pAsset->PackageId;
asset.Version = pAsset->Version;
asset.Type = pAsset->Type;
asset.FileName = pAsset->FileName;
asset.SHA1 = pAsset->SHA1;
asset.SHA256 = pAsset->SHA256;
asset.NotesMarkdown = pAsset->NotesMarkdown;
asset.NotesHtml = pAsset->NotesHtml;
asset.Size = pAsset->Size;
}
}
static inline void copy_to_update_info_dto(vpkc_update_info_t* pUpdate, UpdateInfoDto& update) {
if (pUpdate != nullptr) {
copy_to_asset_dto(&pUpdate->TargetFullRelease, update.TargetFullRelease);
update.IsDowngrade = pUpdate->IsDowngrade;
}
}
static inline void copy_to_asset_pointer(AssetDto& asset, vpkc_asset_t* pAsset) {
if (pAsset != nullptr) {
pAsset->PackageId = _strdup(asset.PackageId.c_str());
pAsset->Version = _strdup(asset.Version.c_str());
pAsset->Type = _strdup(asset.Type.c_str());
pAsset->FileName = _strdup(asset.FileName.c_str());
pAsset->SHA1 = _strdup(asset.SHA1.c_str());
pAsset->SHA256 = _strdup(asset.SHA256.c_str());
pAsset->NotesMarkdown = _strdup(asset.NotesMarkdown.c_str());
pAsset->NotesHtml = _strdup(asset.NotesHtml.c_str());
pAsset->Size = asset.Size;
}
}
static inline void copy_to_asset_pointer(AssetOption& asset, vpkc_asset_t* pAsset) {
if (asset.has_data && pAsset != nullptr) {
copy_to_asset_pointer(asset.data, pAsset);
}
}
static inline void copy_to_update_info_pointer(UpdateInfoOption& update, vpkc_update_info_t* pUpdate) {
if (update.has_data && pUpdate != nullptr) {
copy_to_asset_pointer(update.data.TargetFullRelease, &pUpdate->TargetFullRelease);
pUpdate->IsDowngrade = update.data.IsDowngrade;
}
}
// Update Manager
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, const vpkc_locator_t* locator, vpkc_update_manager_t* pManager);
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion);
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId);
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager);
VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset);
VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate);
VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, const vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress);
VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs);
VPKC_EXPORT bool VPKC_CALL vpkc_new_update_manager(const char* pszUrlOrString, const vpkc_options_t* pOptions, vpkc_locator_t* pLocator, vpkc_update_manager_t* pManager) {
clear_last_error();
try {
LocatorConfigOption locator{};
UpdateOptionsDto options{};
if (pOptions) {
options.AllowVersionDowngrade = pOptions->AllowVersionDowngrade;
if (pOptions->ExplicitChannel) {
options.ExplicitChannel = pOptions->ExplicitChannel;
}
}
copy_to_locator_option(pLocator, locator);
::rust::Box<::UpdateManagerOpaque> manager = bridge_new_update_manager(pszUrlOrString, options, locator);
UpdateManagerOpaque* pOpaque = manager.into_raw();
*pManager = pOpaque;
return true;
} catch (const std::exception& e) {
set_last_error(e.what());
return false;
}
}
VPKC_EXPORT size_t VPKC_CALL vpkc_get_current_version(vpkc_update_manager_t* pManager, char* pszVersion, size_t cVersion) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
::rust::String version = bridge_get_current_version(*pOpaque);
if (version.empty()) {
return 0;
}
size_t len = version.size();
if (pszVersion == nullptr || cVersion == 0) {
return len;
}
if (len > cVersion) {
len = cVersion;
}
memcpy(pszVersion, version.data(), len);
return len;
}
VPKC_EXPORT size_t VPKC_CALL vpkc_get_app_id(vpkc_update_manager_t* pManager, char* pszId, size_t cId) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
::rust::String id = bridge_get_app_id(*pOpaque);
if (id.empty()) {
return 0;
}
size_t len = id.size();
if (pszId == nullptr || cId == 0) {
return len;
}
if (len > cId) {
len = cId;
}
memcpy(pszId, id.data(), len);
return len;
}
VPKC_EXPORT bool VPKC_CALL vpkc_is_portable(vpkc_update_manager_t* pManager) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
return bridge_is_portable(*pOpaque);
}
VPKC_EXPORT bool VPKC_CALL vpkc_update_pending_restart(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
AssetOption asset = bridge_update_pending_restart(*pOpaque);
if (asset.has_data) {
copy_to_asset_pointer(asset, pAsset);
return true;
}
return false;
}
VPKC_EXPORT vpkc_update_check_t VPKC_CALL vpkc_check_for_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate) {
clear_last_error();
try {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
UpdateInfoOption update = bridge_check_for_updates(*pOpaque);
if (update.has_data) {
copy_to_update_info_pointer(update, pUpdate);
return vpkc_update_check_t::UPDATE_AVAILABLE;
}
return vpkc_update_check_t::NO_UPDATE_AVAILABLE;
}
catch (const std::exception& e) {
set_last_error(e.what());
return vpkc_update_check_t::ERROR;
}
}
VPKC_EXPORT bool VPKC_CALL vpkc_download_updates(vpkc_update_manager_t* pManager, vpkc_update_info_t* pUpdate, vpkc_progress_callback_t cbProgress) {
clear_last_error();
try {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
UpdateInfoDto update{};
if (!pUpdate) {
throw new std::runtime_error("pUpdate is a required parameter");
}
copy_to_update_info_dto(pUpdate, update);
DownloadCallbackManager download{};
download.progress_cb = cbProgress;
bridge_download_updates(*pOpaque, update, download);
return true;
}
catch (const std::exception& e) {
set_last_error(e.what());
return false;
}
}
VPKC_EXPORT bool VPKC_CALL vpkc_wait_exit_then_apply_update(vpkc_update_manager_t* pManager, vpkc_asset_t* pAsset, bool bSilent, bool bRestart, char** pRestartArgs, size_t cRestartArgs) {
clear_last_error();
try {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
AssetDto asset{};
if (!pAsset) {
throw new std::runtime_error("pAsset is a required parameter");
}
copy_to_asset_dto(pAsset, asset);
::rust::Vec<::rust::String> restartArgs{};
for (size_t i = 0; i < cRestartArgs; i++) {
restartArgs.push_back(pRestartArgs[i]);
}
bridge_wait_exit_then_apply_update(*pOpaque, asset, bSilent, bRestart, restartArgs);
return true;
}
catch (const std::exception& e) {
set_last_error(e.what());
return false;
}
}
// VelopackApp
bool autoApply = true;
@@ -27,13 +252,7 @@ VPKC_EXPORT void VPKC_CALL vpkc_app_set_args(char** pArgs, size_t cArgs) {
}
}
VPKC_EXPORT void VPKC_CALL vpkc_app_set_locator(vpkc_locator_t* pLocator) {
locator.has_data = true;
locator.data.RootAppDir = pLocator->RootAppDir;
locator.data.UpdateExePath = pLocator->UpdateExePath;
locator.data.PackagesDir = pLocator->PackagesDir;
locator.data.ManifestPath = pLocator->ManifestPath;
locator.data.CurrentBinaryDir = pLocator->CurrentBinaryDir;
locator.data.IsPortable = pLocator->IsPortable;
copy_to_locator_option(pLocator, locator);
}
VPKC_EXPORT void VPKC_CALL vpkc_app_set_hook_after_install(vpkc_hook_callback_t cbAfterInstall) {
hooks.after_install = cbAfterInstall;
@@ -58,8 +277,52 @@ VPKC_EXPORT void VPKC_CALL vpkc_app_run() {
}
// Misc functions
VPKC_EXPORT size_t VPKC_CALL vpkc_get_last_error(char* pszError, size_t cError);
VPKC_EXPORT void VPKC_CALL vpkc_set_log(vpkc_log_callback_t cbLog);
VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager);
VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pManager);
VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pManager);
VPKC_EXPORT void VPKC_CALL vpkc_set_log(vpkc_log_callback_t cbLog) {
logMgr.lob_cb = cbLog;
bridge_set_logger_callback(&logMgr);
}
VPKC_EXPORT void VPKC_CALL vpkc_free_update_manager(vpkc_update_manager_t* pManager) {
UpdateManagerOpaque* pOpaque = reinterpret_cast<UpdateManagerOpaque*>(*pManager);
auto box = ::rust::Box<::UpdateManagerOpaque>::from_raw(pOpaque);
}
VPKC_EXPORT void VPKC_CALL vpkc_free_update_info(vpkc_update_info_t* pUpdateInfo) {
if (pUpdateInfo != nullptr) {
vpkc_free_asset(&pUpdateInfo->TargetFullRelease);
}
}
VPKC_EXPORT void VPKC_CALL vpkc_free_asset(vpkc_asset_t* pAsset) {
if (pAsset != nullptr) {
if (pAsset->PackageId) {
free(pAsset->PackageId);
pAsset->PackageId = nullptr;
}
if (pAsset->Version) {
free(pAsset->Version);
pAsset->Version = nullptr;
}
if (pAsset->Type) {
free(pAsset->Type);
pAsset->Type = nullptr;
}
if (pAsset->FileName) {
free(pAsset->FileName);
pAsset->FileName = nullptr;
}
if (pAsset->SHA1) {
free(pAsset->SHA1);
pAsset->SHA1 = nullptr;
}
if (pAsset->SHA256) {
free(pAsset->SHA256);
pAsset->SHA256 = nullptr;
}
if (pAsset->NotesMarkdown) {
free(pAsset->NotesMarkdown);
pAsset->NotesMarkdown = nullptr;
}
if (pAsset->NotesHtml) {
free(pAsset->NotesHtml);
pAsset->NotesHtml = nullptr;
}
}
}

View File

@@ -9,7 +9,6 @@ struct HookCallbackManager {
vpkc_hook_callback_t after_update = nullptr;
vpkc_hook_callback_t first_run = nullptr;
vpkc_hook_callback_t restarted = nullptr;
void install_hook(::rust::String app_version) const {};
void update_hook(::rust::String app_version) const {};
void obsolete_hook(::rust::String app_version) const {};
@@ -19,9 +18,11 @@ struct HookCallbackManager {
};
struct DownloadCallbackManager {
vpkc_progress_callback_t progress_cb = nullptr;
void download_progress(int16_t progress) const {};
};
struct LoggerCallbackManager {
vpkc_log_callback_t lob_cb = nullptr;
void log(::rust::String level, ::rust::String message) const {};
};

View File

@@ -92,16 +92,16 @@ mod ffi {
// Rust types and signatures exposed to C++.
extern "Rust" {
type UpdateManagerOpaque;
fn bridge_new_update_manager(url_or_path: &CxxString, options: UpdateOptionsDto, locator: LocatorConfigOption) -> Result<Box<UpdateManagerOpaque>>;
fn bridge_new_update_manager(url_or_path: &String, options: &UpdateOptionsDto, locator: &LocatorConfigOption) -> Result<Box<UpdateManagerOpaque>>;
fn bridge_get_current_version(manager: &UpdateManagerOpaque) -> String;
fn bridge_get_app_id(manager: &UpdateManagerOpaque) -> String;
fn bridge_is_portable(manager: &UpdateManagerOpaque) -> bool;
fn bridge_update_pending_restart(manager: &UpdateManagerOpaque) -> AssetOption;
fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result<UpdateInfoOption>;
fn bridge_download_update(manager: &UpdateManagerOpaque, to_download: UpdateInfoDto, progress: UniquePtr<DownloadCallbackManager>) -> Result<()>;
fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_download: AssetDto, silent: bool, restart: bool, restart_args: Vec<String>) -> Result<()>;
unsafe fn bridge_appbuilder_run(cb: &HookCallbackManager, custom_args: &StringArrayOption, locator: &LocatorConfigOption, auto_apply: bool);
fn bridge_set_logger_callback(cb: UniquePtr<LoggerCallbackManager>);
fn bridge_download_updates(manager: &UpdateManagerOpaque, to_download: &UpdateInfoDto, progress: &DownloadCallbackManager) -> Result<()>;
fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_apply: &AssetDto, silent: bool, restart: bool, restart_args: &Vec<String>) -> Result<()>;
fn bridge_appbuilder_run(cb: &HookCallbackManager, custom_args: &StringArrayOption, locator: &LocatorConfigOption, auto_apply: bool);
unsafe fn bridge_set_logger_callback(cb: *mut LoggerCallbackManager);
}
}
@@ -171,9 +171,8 @@ fn to_update_info(info: &ffi::UpdateInfoDto) -> VelopackUpdateInfo {
}
}
fn bridge_new_update_manager(url_or_path: &cxx::CxxString, options: ffi::UpdateOptionsDto, locator: ffi::LocatorConfigOption) -> Result<Box<UpdateManagerOpaque>> {
let url = url_or_path.to_string_lossy();
let source = sources::AutoSource::new(&url);
fn bridge_new_update_manager(url_or_path: &String, options: &ffi::UpdateOptionsDto, locator: &ffi::LocatorConfigOption) -> Result<Box<UpdateManagerOpaque>> {
let source = sources::AutoSource::new(url_or_path);
let update_options = to_update_options(&options);
if locator.has_data {
@@ -218,7 +217,7 @@ fn bridge_check_for_updates(manager: &UpdateManagerOpaque) -> Result<ffi::Update
}
}
fn bridge_download_update(manager: &UpdateManagerOpaque, to_download: ffi::UpdateInfoDto, cb: cxx::UniquePtr<ffi::DownloadCallbackManager>) -> Result<()> {
fn bridge_download_updates(manager: &UpdateManagerOpaque, to_download: &ffi::UpdateInfoDto, cb: &ffi::DownloadCallbackManager) -> Result<()> {
let info = to_update_info(&to_download);
let (progress_sender, progress_receiver) = std::sync::mpsc::channel::<i16>();
@@ -261,8 +260,8 @@ fn bridge_download_update(manager: &UpdateManagerOpaque, to_download: ffi::Updat
}
}
fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_download: ffi::AssetDto, silent: bool, restart: bool, restart_args: Vec<String>) -> Result<()> {
let asset = to_asset(&to_download);
fn bridge_wait_exit_then_apply_update(manager: &UpdateManagerOpaque, to_apply: &ffi::AssetDto, silent: bool, restart: bool, restart_args: &Vec<String>) -> Result<()> {
let asset = to_asset(&to_apply);
manager.obj.wait_exit_then_apply_updates(&asset, silent, restart, restart_args)?;
Ok(())
}
@@ -344,10 +343,8 @@ fn get_logger() -> Option<*mut ffi::LoggerCallbackManager> {
}
}
fn bridge_set_logger_callback(cb: cxx::UniquePtr<ffi::LoggerCallbackManager>) {
unsafe fn bridge_set_logger_callback(cb: *mut ffi::LoggerCallbackManager) {
let _ = log::set_logger(&LOGGER);
log::set_max_level(log::LevelFilter::Trace);
let cb = cb.into_raw();
store_logger(cb);
}