mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Fix various bugs with rust delta process
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
//! This header provides the C++ API for the Velopack library.
|
||||
//! This C++ API is a thin wrapper around the C API, providing a more idiomatic C++ interface.
|
||||
//! You should not mix and match the C and C++ APIs in the same program.
|
||||
#ifndef VELOPACK_HPP
|
||||
#define VELOPACK_HPP
|
||||
|
||||
@@ -78,6 +77,14 @@ static inline void free_c_string_vec(char** arr, size_t size)
|
||||
delete[] arr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline T unwrap(const std::optional<T>& opt, const std::string& message = "Expected value not present") {
|
||||
if (!opt.has_value()) {
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
return opt.value();
|
||||
}
|
||||
|
||||
// !! AUTO-GENERATED-START CPP_TYPES
|
||||
|
||||
/** VelopackLocator provides some utility functions for locating the current app important paths (eg. path to packages, update binary, and so forth). */
|
||||
@@ -99,11 +106,11 @@ struct VelopackLocatorConfig {
|
||||
static inline std::optional<VelopackLocatorConfig> to_cpp_VelopackLocatorConfig(const vpkc_locator_config_t* dto) {
|
||||
if (dto == nullptr) { return std::nullopt; }
|
||||
return std::optional<VelopackLocatorConfig>({
|
||||
to_cpp_string(dto->RootAppDir).value(),
|
||||
to_cpp_string(dto->UpdateExePath).value(),
|
||||
to_cpp_string(dto->PackagesDir).value(),
|
||||
to_cpp_string(dto->ManifestPath).value(),
|
||||
to_cpp_string(dto->CurrentBinaryDir).value(),
|
||||
unwrap(to_cpp_string(dto->RootAppDir), "Required property RootAppDir was null"),
|
||||
unwrap(to_cpp_string(dto->UpdateExePath), "Required property UpdateExePath was null"),
|
||||
unwrap(to_cpp_string(dto->PackagesDir), "Required property PackagesDir was null"),
|
||||
unwrap(to_cpp_string(dto->ManifestPath), "Required property ManifestPath was null"),
|
||||
unwrap(to_cpp_string(dto->CurrentBinaryDir), "Required property CurrentBinaryDir was null"),
|
||||
dto->IsPortable,
|
||||
});
|
||||
}
|
||||
@@ -115,12 +122,12 @@ static inline std::vector<VelopackLocatorConfig> to_cpp_VelopackLocatorConfig_ve
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
auto dto = arr[i];
|
||||
if (dto == nullptr) { continue; }
|
||||
result.push_back(to_cpp_VelopackLocatorConfig(dto).value());
|
||||
result.push_back(unwrap(to_cpp_VelopackLocatorConfig(dto)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline vpkc_locator_config_t* alloc_c_VelopackLocatorConfig(const VelopackLocatorConfig* dto) {
|
||||
static inline vpkc_locator_config_t* alloc_c_VelopackLocatorConfig_ptr(const VelopackLocatorConfig* dto) {
|
||||
if (dto == nullptr) { return nullptr; }
|
||||
vpkc_locator_config_t* obj = new vpkc_locator_config_t{};
|
||||
obj->RootAppDir = alloc_c_string(dto->RootAppDir);
|
||||
@@ -134,7 +141,8 @@ static inline vpkc_locator_config_t* alloc_c_VelopackLocatorConfig(const Velopac
|
||||
|
||||
static inline vpkc_locator_config_t* alloc_c_VelopackLocatorConfig(const std::optional<VelopackLocatorConfig>& dto) {
|
||||
if (!dto.has_value()) { return nullptr; }
|
||||
return alloc_c_VelopackLocatorConfig(dto.value());
|
||||
VelopackLocatorConfig obj = unwrap(dto);
|
||||
return alloc_c_VelopackLocatorConfig_ptr(&obj);
|
||||
}
|
||||
|
||||
static inline vpkc_locator_config_t** alloc_c_VelopackLocatorConfig_vec(const std::vector<VelopackLocatorConfig>& dto, size_t* count) {
|
||||
@@ -194,15 +202,15 @@ struct VelopackAsset {
|
||||
static inline std::optional<VelopackAsset> to_cpp_VelopackAsset(const vpkc_asset_t* dto) {
|
||||
if (dto == nullptr) { return std::nullopt; }
|
||||
return std::optional<VelopackAsset>({
|
||||
to_cpp_string(dto->PackageId).value(),
|
||||
to_cpp_string(dto->Version).value(),
|
||||
to_cpp_string(dto->Type).value(),
|
||||
to_cpp_string(dto->FileName).value(),
|
||||
to_cpp_string(dto->SHA1).value(),
|
||||
to_cpp_string(dto->SHA256).value(),
|
||||
unwrap(to_cpp_string(dto->PackageId), "Required property PackageId was null"),
|
||||
unwrap(to_cpp_string(dto->Version), "Required property Version was null"),
|
||||
unwrap(to_cpp_string(dto->Type), "Required property Type was null"),
|
||||
unwrap(to_cpp_string(dto->FileName), "Required property FileName was null"),
|
||||
unwrap(to_cpp_string(dto->SHA1), "Required property SHA1 was null"),
|
||||
unwrap(to_cpp_string(dto->SHA256), "Required property SHA256 was null"),
|
||||
dto->Size,
|
||||
to_cpp_string(dto->NotesMarkdown).value(),
|
||||
to_cpp_string(dto->NotesHtml).value(),
|
||||
unwrap(to_cpp_string(dto->NotesMarkdown), "Required property NotesMarkdown was null"),
|
||||
unwrap(to_cpp_string(dto->NotesHtml), "Required property NotesHtml was null"),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,12 +221,12 @@ static inline std::vector<VelopackAsset> to_cpp_VelopackAsset_vec(const vpkc_ass
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
auto dto = arr[i];
|
||||
if (dto == nullptr) { continue; }
|
||||
result.push_back(to_cpp_VelopackAsset(dto).value());
|
||||
result.push_back(unwrap(to_cpp_VelopackAsset(dto)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline vpkc_asset_t* alloc_c_VelopackAsset(const VelopackAsset* dto) {
|
||||
static inline vpkc_asset_t* alloc_c_VelopackAsset_ptr(const VelopackAsset* dto) {
|
||||
if (dto == nullptr) { return nullptr; }
|
||||
vpkc_asset_t* obj = new vpkc_asset_t{};
|
||||
obj->PackageId = alloc_c_string(dto->PackageId);
|
||||
@@ -235,7 +243,8 @@ static inline vpkc_asset_t* alloc_c_VelopackAsset(const VelopackAsset* dto) {
|
||||
|
||||
static inline vpkc_asset_t* alloc_c_VelopackAsset(const std::optional<VelopackAsset>& dto) {
|
||||
if (!dto.has_value()) { return nullptr; }
|
||||
return alloc_c_VelopackAsset(dto.value());
|
||||
VelopackAsset obj = unwrap(dto);
|
||||
return alloc_c_VelopackAsset_ptr(&obj);
|
||||
}
|
||||
|
||||
static inline vpkc_asset_t** alloc_c_VelopackAsset_vec(const std::vector<VelopackAsset>& dto, size_t* count) {
|
||||
@@ -292,7 +301,7 @@ struct UpdateInfo {
|
||||
static inline std::optional<UpdateInfo> to_cpp_UpdateInfo(const vpkc_update_info_t* dto) {
|
||||
if (dto == nullptr) { return std::nullopt; }
|
||||
return std::optional<UpdateInfo>({
|
||||
to_cpp_VelopackAsset(dto->TargetFullRelease).value(),
|
||||
unwrap(to_cpp_VelopackAsset(dto->TargetFullRelease), "Required property TargetFullRelease was null"),
|
||||
to_cpp_VelopackAsset(dto->BaseRelease),
|
||||
to_cpp_VelopackAsset_vec(dto->DeltasToTarget, dto->DeltasToTargetCount),
|
||||
dto->IsDowngrade,
|
||||
@@ -306,12 +315,12 @@ static inline std::vector<UpdateInfo> to_cpp_UpdateInfo_vec(const vpkc_update_in
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
auto dto = arr[i];
|
||||
if (dto == nullptr) { continue; }
|
||||
result.push_back(to_cpp_UpdateInfo(dto).value());
|
||||
result.push_back(unwrap(to_cpp_UpdateInfo(dto)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline vpkc_update_info_t* alloc_c_UpdateInfo(const UpdateInfo* dto) {
|
||||
static inline vpkc_update_info_t* alloc_c_UpdateInfo_ptr(const UpdateInfo* dto) {
|
||||
if (dto == nullptr) { return nullptr; }
|
||||
vpkc_update_info_t* obj = new vpkc_update_info_t{};
|
||||
obj->TargetFullRelease = alloc_c_VelopackAsset(dto->TargetFullRelease);
|
||||
@@ -323,7 +332,8 @@ static inline vpkc_update_info_t* alloc_c_UpdateInfo(const UpdateInfo* dto) {
|
||||
|
||||
static inline vpkc_update_info_t* alloc_c_UpdateInfo(const std::optional<UpdateInfo>& dto) {
|
||||
if (!dto.has_value()) { return nullptr; }
|
||||
return alloc_c_UpdateInfo(dto.value());
|
||||
UpdateInfo obj = unwrap(dto);
|
||||
return alloc_c_UpdateInfo_ptr(&obj);
|
||||
}
|
||||
|
||||
static inline vpkc_update_info_t** alloc_c_UpdateInfo_vec(const std::vector<UpdateInfo>& dto, size_t* count) {
|
||||
@@ -398,12 +408,12 @@ static inline std::vector<UpdateOptions> to_cpp_UpdateOptions_vec(const vpkc_upd
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
auto dto = arr[i];
|
||||
if (dto == nullptr) { continue; }
|
||||
result.push_back(to_cpp_UpdateOptions(dto).value());
|
||||
result.push_back(unwrap(to_cpp_UpdateOptions(dto)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline vpkc_update_options_t* alloc_c_UpdateOptions(const UpdateOptions* dto) {
|
||||
static inline vpkc_update_options_t* alloc_c_UpdateOptions_ptr(const UpdateOptions* dto) {
|
||||
if (dto == nullptr) { return nullptr; }
|
||||
vpkc_update_options_t* obj = new vpkc_update_options_t{};
|
||||
obj->AllowVersionDowngrade = dto->AllowVersionDowngrade;
|
||||
@@ -414,7 +424,8 @@ static inline vpkc_update_options_t* alloc_c_UpdateOptions(const UpdateOptions*
|
||||
|
||||
static inline vpkc_update_options_t* alloc_c_UpdateOptions(const std::optional<UpdateOptions>& dto) {
|
||||
if (!dto.has_value()) { return nullptr; }
|
||||
return alloc_c_UpdateOptions(dto.value());
|
||||
UpdateOptions obj = unwrap(dto);
|
||||
return alloc_c_UpdateOptions_ptr(&obj);
|
||||
}
|
||||
|
||||
static inline vpkc_update_options_t** alloc_c_UpdateOptions_vec(const std::vector<UpdateOptions>& dto, size_t* count) {
|
||||
@@ -669,8 +680,8 @@ public:
|
||||
* @param locator Override the default locator configuration (usually used for testing / mocks).
|
||||
*/
|
||||
UpdateManager(const std::string& urlOrPath, const UpdateOptions* options = nullptr, const VelopackLocatorConfig* locator = nullptr) {
|
||||
vpkc_update_options_t* pOptions = alloc_c_UpdateOptions(options);
|
||||
vpkc_locator_config_t* pLocator = alloc_c_VelopackLocatorConfig(locator);
|
||||
vpkc_update_options_t* pOptions = alloc_c_UpdateOptions_ptr(options);
|
||||
vpkc_locator_config_t* pLocator = alloc_c_VelopackLocatorConfig_ptr(locator);
|
||||
bool result = vpkc_new_update_manager(urlOrPath.c_str(), pOptions, pLocator, &m_pManager);
|
||||
free_c_UpdateOptions(pOptions);
|
||||
free_c_VelopackLocatorConfig(pLocator);
|
||||
@@ -687,8 +698,8 @@ public:
|
||||
*/
|
||||
template <typename T, typename = std::enable_if_t<std::is_base_of_v<IUpdateSource, T>>>
|
||||
UpdateManager(std::unique_ptr<T> pUpdateSource, const UpdateOptions* options = nullptr, const VelopackLocatorConfig* locator = nullptr) {
|
||||
vpkc_update_options_t* pOptions = alloc_c_UpdateOptions(options);
|
||||
vpkc_locator_config_t* pLocator = alloc_c_VelopackLocatorConfig(locator);
|
||||
vpkc_update_options_t* pOptions = alloc_c_UpdateOptions_ptr(options);
|
||||
vpkc_locator_config_t* pLocator = alloc_c_VelopackLocatorConfig_ptr(locator);
|
||||
m_pUpdateSource = std::unique_ptr<IUpdateSource>(static_cast<IUpdateSource*>(pUpdateSource.release()));
|
||||
vpkc_update_source_t* pSource = m_pUpdateSource->m_pSource;
|
||||
bool result = vpkc_new_update_manager_with_source(pSource, pOptions, pLocator, &m_pManager);
|
||||
@@ -703,7 +714,10 @@ public:
|
||||
* Destructor for UpdateManager.
|
||||
*/
|
||||
~UpdateManager() {
|
||||
vpkc_free_update_manager(m_pManager);
|
||||
if (m_pManager != nullptr) {
|
||||
vpkc_free_update_manager(m_pManager);
|
||||
m_pManager = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ use anyhow::{bail, Result};
|
||||
use libc::{c_char, c_void, size_t};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::path::PathBuf;
|
||||
use std::mem::size_of;
|
||||
use velopack::{locator::VelopackLocatorConfig, UpdateInfo, UpdateOptions, VelopackAsset};
|
||||
|
||||
/// The result of a call to check for updates. This can indicate that an update is available, or that an error occurred.
|
||||
@@ -89,9 +90,10 @@ pub fn allocate_PathBuf(p: &PathBuf) -> *mut c_char {
|
||||
|
||||
pub unsafe fn free_String(psz: *mut c_char) {
|
||||
if !psz.is_null() {
|
||||
let _ = unsafe { CString::from_raw(psz) };
|
||||
drop(CString::from_raw(psz));
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn free_PathBuf(psz: *mut c_char) {
|
||||
free_String(psz);
|
||||
}
|
||||
@@ -181,6 +183,7 @@ pub unsafe fn allocate_VelopackLocatorConfig_vec(dto: &Vec<VelopackLocatorConfig
|
||||
}
|
||||
log::debug!("vpkc_locator_config_t vector allocated");
|
||||
let count_value = dto.len() as size_t;
|
||||
*count = count_value;
|
||||
let mut assets = Vec::with_capacity(count_value as usize);
|
||||
for i in 0..count_value {
|
||||
let ptr = allocate_VelopackLocatorConfig(&dto[i as usize]);
|
||||
@@ -297,6 +300,7 @@ pub unsafe fn allocate_VelopackAsset_vec(dto: &Vec<VelopackAsset>, count: *mut s
|
||||
}
|
||||
log::debug!("vpkc_asset_t vector allocated");
|
||||
let count_value = dto.len() as size_t;
|
||||
*count = count_value;
|
||||
let mut assets = Vec::with_capacity(count_value as usize);
|
||||
for i in 0..count_value {
|
||||
let ptr = allocate_VelopackAsset(&dto[i as usize]);
|
||||
@@ -400,6 +404,7 @@ pub unsafe fn allocate_UpdateInfo_vec(dto: &Vec<UpdateInfo>, count: *mut size_t)
|
||||
}
|
||||
log::debug!("vpkc_update_info_t vector allocated");
|
||||
let count_value = dto.len() as size_t;
|
||||
*count = count_value;
|
||||
let mut assets = Vec::with_capacity(count_value as usize);
|
||||
for i in 0..count_value {
|
||||
let ptr = allocate_UpdateInfo(&dto[i as usize]);
|
||||
@@ -500,6 +505,7 @@ pub unsafe fn allocate_UpdateOptions_vec(dto: &Vec<UpdateOptions>, count: *mut s
|
||||
}
|
||||
log::debug!("vpkc_update_options_t vector allocated");
|
||||
let count_value = dto.len() as size_t;
|
||||
*count = count_value;
|
||||
let mut assets = Vec::with_capacity(count_value as usize);
|
||||
for i in 0..count_value {
|
||||
let ptr = allocate_UpdateOptions(&dto[i as usize]);
|
||||
|
||||
@@ -16,7 +16,7 @@ static inline std::optional<{{struct_rust_name}}> to_cpp_{{struct_rust_name}}(co
|
||||
return std::optional<{{struct_rust_name}}>({
|
||||
{{#each fields}}
|
||||
{{#if field_primitive}}dto->{{field_name}},{{/if~}}
|
||||
{{#if field_normal}}to_cpp_{{field_cpp_type}}(dto->{{field_name}}){{~#unless field_optional}}.value(){{/unless}},{{/if~}}
|
||||
{{#if field_normal}}{{#unless field_optional}}unwrap({{/unless}}to_cpp_{{field_cpp_type}}(dto->{{field_name}}){{~#unless field_optional}}, "Required property {{field_name}} was null"){{/unless}},{{/if~}}
|
||||
{{#if field_vector}}to_cpp_{{field_cpp_type}}_vec(dto->{{field_name}}, dto->{{field_name}}Count),{{/if}}
|
||||
{{/each}}
|
||||
});
|
||||
@@ -29,12 +29,12 @@ static inline std::vector<{{struct_rust_name}}> to_cpp_{{struct_rust_name}}_vec(
|
||||
for (size_t i = 0; i < c; ++i) {
|
||||
auto dto = arr[i];
|
||||
if (dto == nullptr) { continue; }
|
||||
result.push_back(to_cpp_{{struct_rust_name}}(dto).value());
|
||||
result.push_back(unwrap(to_cpp_{{struct_rust_name}}(dto)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline {{struct_c_name}}* alloc_c_{{struct_rust_name}}(const {{struct_rust_name}}* dto) {
|
||||
static inline {{struct_c_name}}* alloc_c_{{struct_rust_name}}_ptr(const {{struct_rust_name}}* dto) {
|
||||
if (dto == nullptr) { return nullptr; }
|
||||
{{struct_c_name}}* obj = new {{struct_c_name}}{};
|
||||
{{#each fields}}
|
||||
@@ -47,7 +47,8 @@ static inline {{struct_c_name}}* alloc_c_{{struct_rust_name}}(const {{struct_rus
|
||||
|
||||
static inline {{struct_c_name}}* alloc_c_{{struct_rust_name}}(const std::optional<{{struct_rust_name}}>& dto) {
|
||||
if (!dto.has_value()) { return nullptr; }
|
||||
return alloc_c_{{struct_rust_name}}(dto.value());
|
||||
{{struct_rust_name}} obj = unwrap(dto);
|
||||
return alloc_c_{{struct_rust_name}}_ptr(&obj);
|
||||
}
|
||||
|
||||
static inline {{struct_c_name}}** alloc_c_{{struct_rust_name}}_vec(const std::vector<{{struct_rust_name}}>& dto, size_t* count) {
|
||||
|
||||
@@ -63,6 +63,7 @@ pub unsafe fn allocate_{{struct_rust_name}}_vec(dto: &Vec<{{struct_rust_name}}>,
|
||||
}
|
||||
log::debug!("{{struct_c_name}} vector allocated");
|
||||
let count_value = dto.len() as size_t;
|
||||
*count = count_value;
|
||||
let mut assets = Vec::with_capacity(count_value as usize);
|
||||
for i in 0..count_value {
|
||||
let ptr = allocate_{{struct_rust_name}}(&dto[i as usize]);
|
||||
|
||||
@@ -398,7 +398,7 @@ impl UpdateManager {
|
||||
|
||||
fs::create_dir_all(packages_dir)?;
|
||||
let final_target_file = packages_dir.join(name);
|
||||
let partial_file = final_target_file.with_extension(".partial");
|
||||
let partial_file = final_target_file.with_extension("partial");
|
||||
|
||||
if final_target_file.exists() {
|
||||
info!("Package already exists on disk, skipping download: '{}'", final_target_file.to_string_lossy());
|
||||
@@ -407,11 +407,10 @@ impl UpdateManager {
|
||||
|
||||
let old_nupkg_pattern = format!("{}/*.nupkg", packages_dir.to_string_lossy());
|
||||
let old_partial_pattern = format!("{}/*.partial", packages_dir.to_string_lossy());
|
||||
let delta_pattern = format!("{}/-delta.nupkg", packages_dir.to_string_lossy());
|
||||
let delta_pattern = format!("{}/*-delta.nupkg", packages_dir.to_string_lossy());
|
||||
let mut to_delete = Vec::new();
|
||||
|
||||
fn find_files_to_delete(pattern: &str, to_delete: &mut Vec<String>) {
|
||||
info!("Searching for packages to clean: '{}'", pattern);
|
||||
match glob::glob(pattern) {
|
||||
Ok(paths) => {
|
||||
for path in paths.into_iter().flatten() {
|
||||
@@ -434,14 +433,14 @@ impl UpdateManager {
|
||||
info!("Falling back to full update...");
|
||||
self.source.download_release_entry(&update.TargetFullRelease, &partial_file.to_string_lossy(), progress)?;
|
||||
self.verify_package_checksum(&partial_file, &update.TargetFullRelease)?;
|
||||
info!("Successfully downloaded file: '{}'", partial_file.to_string_lossy());
|
||||
}
|
||||
} else {
|
||||
self.source.download_release_entry(&update.TargetFullRelease, &partial_file.to_string_lossy(), progress)?;
|
||||
self.verify_package_checksum(&partial_file, &update.TargetFullRelease)?;
|
||||
info!("Successfully downloaded file: '{}'", partial_file.to_string_lossy());
|
||||
}
|
||||
|
||||
info!("Successfully downloaded file: '{}'", partial_file.to_string_lossy());
|
||||
|
||||
info!("Renaming partial file to final target: '{}'", final_target_file.to_string_lossy());
|
||||
fs::rename(&partial_file, &final_target_file)?;
|
||||
|
||||
@@ -477,6 +476,12 @@ impl UpdateManager {
|
||||
progress: Option<Sender<i16>>,
|
||||
) -> Result<(), Error> {
|
||||
let packages_dir = self.locator.get_packages_dir();
|
||||
let base_release_path = packages_dir.join(&update.BaseRelease.as_ref().unwrap().FileName);
|
||||
let base_release_path = base_release_path.to_string_lossy().to_string();
|
||||
let output_path = target_file.to_string_lossy().to_string();
|
||||
|
||||
let mut args: Vec<String> = ["patch", "--old", &base_release_path, "--output", &output_path].iter().map(|s| s.to_string()).collect();
|
||||
|
||||
for (i, delta) in update.DeltasToTarget.iter().enumerate() {
|
||||
let delta_file = packages_dir.join(&delta.FileName);
|
||||
let partial_file = delta_file.with_extension("partial");
|
||||
@@ -490,18 +495,16 @@ impl UpdateManager {
|
||||
if let Some(progress) = &progress {
|
||||
let _ = progress.send(((i as f64 / update.DeltasToTarget.len() as f64) * 70.0) as i16);
|
||||
}
|
||||
}
|
||||
|
||||
let mut args: Vec<String> =
|
||||
["patch", "--old", &update.BaseRelease.as_ref().unwrap().FileName, "--output"].iter().map(|s| s.to_string()).collect();
|
||||
args.push(target_file.to_string_lossy().to_string());
|
||||
for delta in update.DeltasToTarget.iter() {
|
||||
args.push("--delta".to_string());
|
||||
let path = packages_dir.join(&delta.FileName);
|
||||
args.push(path.to_string_lossy().to_string());
|
||||
args.push(delta_file.to_string_lossy().to_string());
|
||||
}
|
||||
|
||||
info!("Applying {} patches to {}.", update.DeltasToTarget.len(), target_file.to_string_lossy());
|
||||
info!("Applying {} patches to {}.", update.DeltasToTarget.len(), output_path);
|
||||
|
||||
if let Some(progress) = &progress {
|
||||
let _ = progress.send(70);
|
||||
}
|
||||
|
||||
let output = std::process::Command::new(self.locator.get_update_path()).args(args).output()?;
|
||||
if output.status.success() {
|
||||
|
||||
Reference in New Issue
Block a user