mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
code formatting
This commit is contained in:
@@ -3,40 +3,20 @@ use std::fs;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Get the workspace version
|
// Get the workspace version
|
||||||
let version = get_workspace_version().unwrap_or_else(|| {
|
let version = get_workspace_version().unwrap_or_else(|| env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "0.1.0".to_string()));
|
||||||
env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "0.1.0".to_string())
|
|
||||||
});
|
|
||||||
|
|
||||||
let python_version = convert_to_python_version(&version);
|
let python_version = convert_to_python_version(&version);
|
||||||
|
|
||||||
// Set environment variables for PyO3
|
// Set environment variables for PyO3
|
||||||
println!("cargo:rustc-env=PYTHON_VERSION={}", python_version);
|
println!("cargo:rustc-env=PYTHON_VERSION={}", python_version);
|
||||||
|
|
||||||
// Try setting the package version for PyO3 to pick up
|
// Try setting the package version for PyO3 to pick up
|
||||||
println!("cargo:metadata=version={}", python_version);
|
println!("cargo:metadata=version={}", python_version);
|
||||||
|
|
||||||
// Also set it as a cfg value
|
// Also set it as a cfg value
|
||||||
println!("cargo:rustc-cfg=version=\"{}\"", python_version);
|
println!("cargo:rustc-cfg=version=\"{}\"", python_version);
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=../../Cargo.toml");
|
println!("cargo:rerun-if-changed=../../Cargo.toml");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,33 +24,32 @@ fn get_workspace_version() -> Option<String> {
|
|||||||
// Navigate up to workspace root and read Cargo.toml
|
// Navigate up to workspace root and read Cargo.toml
|
||||||
let manifest_dir = env::var("CARGO_MANIFEST_DIR").ok()?;
|
let manifest_dir = env::var("CARGO_MANIFEST_DIR").ok()?;
|
||||||
let workspace_toml = Path::new(&manifest_dir)
|
let workspace_toml = Path::new(&manifest_dir)
|
||||||
.parent()? // src
|
.parent()? // src
|
||||||
.parent()? // velopack root
|
.parent()? // velopack root
|
||||||
.join("Cargo.toml");
|
.join("Cargo.toml");
|
||||||
|
|
||||||
if !workspace_toml.exists() {
|
if !workspace_toml.exists() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = fs::read_to_string(&workspace_toml).ok()?;
|
let content = fs::read_to_string(&workspace_toml).ok()?;
|
||||||
|
|
||||||
// Simple parsing to extract version from [workspace.package] section
|
// Simple parsing to extract version from [workspace.package] section
|
||||||
let mut in_workspace_package = false;
|
let mut in_workspace_package = false;
|
||||||
for (_line_num, line) in content.lines().enumerate() {
|
for (_line_num, line) in content.lines().enumerate() {
|
||||||
let trimmed = line.trim();
|
let trimmed = line.trim();
|
||||||
|
|
||||||
if trimmed == "[workspace.package]" {
|
if trimmed == "[workspace.package]" {
|
||||||
in_workspace_package = true;
|
in_workspace_package = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if trimmed.starts_with('[') && trimmed != "[workspace.package]" {
|
if trimmed.starts_with('[') && trimmed != "[workspace.package]" {
|
||||||
if in_workspace_package {
|
if in_workspace_package {}
|
||||||
}
|
|
||||||
in_workspace_package = false;
|
in_workspace_package = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if in_workspace_package && trimmed.starts_with("version") {
|
if in_workspace_package && trimmed.starts_with("version") {
|
||||||
if let Some(equals_pos) = trimmed.find('=') {
|
if let Some(equals_pos) = trimmed.find('=') {
|
||||||
let version_part = &trimmed[equals_pos + 1..].trim();
|
let version_part = &trimmed[equals_pos + 1..].trim();
|
||||||
@@ -80,7 +59,7 @@ fn get_workspace_version() -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,38 +69,38 @@ fn convert_to_python_version(rust_version: &str) -> String {
|
|||||||
let base = &rust_version[..git_pos];
|
let base = &rust_version[..git_pos];
|
||||||
return ensure_xyz_format(base);
|
return ensure_xyz_format(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle local development versions like "0.0.0-local" - drop local suffix
|
// Handle local development versions like "0.0.0-local" - drop local suffix
|
||||||
if rust_version.ends_with("-local") {
|
if rust_version.ends_with("-local") {
|
||||||
let base = rust_version.trim_end_matches("-local");
|
let base = rust_version.trim_end_matches("-local");
|
||||||
return ensure_xyz_format(base);
|
return ensure_xyz_format(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle Rust pre-release patterns and convert to Python equivalents
|
// Handle Rust pre-release patterns and convert to Python equivalents
|
||||||
if rust_version.contains("-alpha") {
|
if rust_version.contains("-alpha") {
|
||||||
let base = rust_version.split("-alpha").next().unwrap();
|
let base = rust_version.split("-alpha").next().unwrap();
|
||||||
let alpha_num = extract_prerelease_number(rust_version, "-alpha");
|
let alpha_num = extract_prerelease_number(rust_version, "-alpha");
|
||||||
return format!("{}a{}", ensure_xyz_format(base), alpha_num);
|
return format!("{}a{}", ensure_xyz_format(base), alpha_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
if rust_version.contains("-beta") {
|
if rust_version.contains("-beta") {
|
||||||
let base = rust_version.split("-beta").next().unwrap();
|
let base = rust_version.split("-beta").next().unwrap();
|
||||||
let beta_num = extract_prerelease_number(rust_version, "-beta");
|
let beta_num = extract_prerelease_number(rust_version, "-beta");
|
||||||
return format!("{}b{}", ensure_xyz_format(base), beta_num);
|
return format!("{}b{}", ensure_xyz_format(base), beta_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
if rust_version.contains("-rc") {
|
if rust_version.contains("-rc") {
|
||||||
let base = rust_version.split("-rc").next().unwrap();
|
let base = rust_version.split("-rc").next().unwrap();
|
||||||
let rc_num = extract_prerelease_number(rust_version, "-rc");
|
let rc_num = extract_prerelease_number(rust_version, "-rc");
|
||||||
return format!("{}rc{}", ensure_xyz_format(base), rc_num);
|
return format!("{}rc{}", ensure_xyz_format(base), rc_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For any other dash-separated version, just take the base
|
// For any other dash-separated version, just take the base
|
||||||
if rust_version.contains('-') {
|
if rust_version.contains('-') {
|
||||||
let base = rust_version.split('-').next().unwrap();
|
let base = rust_version.split('-').next().unwrap();
|
||||||
return ensure_xyz_format(base);
|
return ensure_xyz_format(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
ensure_xyz_format(rust_version)
|
ensure_xyz_format(rust_version)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,23 +138,23 @@ mod tests {
|
|||||||
// Git versions - drop git ref
|
// Git versions - drop git ref
|
||||||
assert_eq!(convert_to_python_version("0.0.1213-g57cf68d"), "0.0.1213");
|
assert_eq!(convert_to_python_version("0.0.1213-g57cf68d"), "0.0.1213");
|
||||||
assert_eq!(convert_to_python_version("1.2-g57cf68d"), "1.2.0");
|
assert_eq!(convert_to_python_version("1.2-g57cf68d"), "1.2.0");
|
||||||
|
|
||||||
// Local versions - drop local suffix
|
// Local versions - drop local suffix
|
||||||
assert_eq!(convert_to_python_version("0.0.0-local"), "0.0.0");
|
assert_eq!(convert_to_python_version("0.0.0-local"), "0.0.0");
|
||||||
assert_eq!(convert_to_python_version("1.2.3-local"), "1.2.3");
|
assert_eq!(convert_to_python_version("1.2.3-local"), "1.2.3");
|
||||||
|
|
||||||
// Pre-release versions - convert to Python format
|
// Pre-release versions - convert to Python format
|
||||||
assert_eq!(convert_to_python_version("1.0.0-alpha.1"), "1.0.0a1");
|
assert_eq!(convert_to_python_version("1.0.0-alpha.1"), "1.0.0a1");
|
||||||
assert_eq!(convert_to_python_version("1.0.0-alpha"), "1.0.0a0");
|
assert_eq!(convert_to_python_version("1.0.0-alpha"), "1.0.0a0");
|
||||||
assert_eq!(convert_to_python_version("1.0.0-beta.2"), "1.0.0b2");
|
assert_eq!(convert_to_python_version("1.0.0-beta.2"), "1.0.0b2");
|
||||||
assert_eq!(convert_to_python_version("1.0.0-rc.1"), "1.0.0rc1");
|
assert_eq!(convert_to_python_version("1.0.0-rc.1"), "1.0.0rc1");
|
||||||
|
|
||||||
// Standard versions - ensure x.y.z format
|
// Standard versions - ensure x.y.z format
|
||||||
assert_eq!(convert_to_python_version("1.0.0"), "1.0.0");
|
assert_eq!(convert_to_python_version("1.0.0"), "1.0.0");
|
||||||
assert_eq!(convert_to_python_version("1.2"), "1.2.0");
|
assert_eq!(convert_to_python_version("1.2"), "1.2.0");
|
||||||
assert_eq!(convert_to_python_version("1"), "1.0.0");
|
assert_eq!(convert_to_python_version("1"), "1.0.0");
|
||||||
|
|
||||||
// Other dash-separated versions - take base only
|
// Other dash-separated versions - take base only
|
||||||
assert_eq!(convert_to_python_version("1.0.0-something-else"), "1.0.0");
|
assert_eq!(convert_to_python_version("1.0.0-something-else"), "1.0.0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,8 +85,7 @@ impl VelopackAppWrapper {
|
|||||||
/// Runs the Velopack startup logic
|
/// Runs the Velopack startup logic
|
||||||
pub fn run(&mut self, _py: Python) -> PyResult<()> {
|
pub fn run(&mut self, _py: Python) -> PyResult<()> {
|
||||||
// Create the Rust VelopackApp with our stored configuration
|
// Create the Rust VelopackApp with our stored configuration
|
||||||
let mut app = VelopackAppRust::build()
|
let mut app = VelopackAppRust::build().set_auto_apply_on_startup(self.auto_apply);
|
||||||
.set_auto_apply_on_startup(self.auto_apply);
|
|
||||||
|
|
||||||
// Set args if provided
|
// Set args if provided
|
||||||
if let Some(ref args) = self.args {
|
if let Some(ref args) = self.args {
|
||||||
@@ -175,4 +174,3 @@ impl VelopackAppWrapper {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use pyo3::prelude::*;
|
|
||||||
use pyo3::exceptions::PyException;
|
use pyo3::exceptions::PyException;
|
||||||
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
#[pyclass(name="VelopackError", extends=PyException, module="velopack.exceptions")]
|
#[pyclass(name="VelopackError", extends=PyException, module="velopack.exceptions")]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -18,4 +18,3 @@ impl VelopackError {
|
|||||||
self.message.clone()
|
self.message.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +1,37 @@
|
|||||||
use asset::PyUpdateInfo;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::types::PyModule;
|
use pyo3::types::PyModule;
|
||||||
|
|
||||||
mod asset;
|
mod types;
|
||||||
pub use asset::PyVelopackAsset;
|
use types::*;
|
||||||
|
|
||||||
|
|
||||||
mod exceptions;
|
mod exceptions;
|
||||||
pub use exceptions::VelopackError;
|
use exceptions::VelopackError;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
pub use app::VelopackAppWrapper;
|
use app::VelopackAppWrapper;
|
||||||
|
|
||||||
mod manager;
|
mod manager;
|
||||||
pub use manager::UpdateManagerWrapper;
|
use manager::UpdateManagerWrapper;
|
||||||
|
|
||||||
|
|
||||||
#[pymodule]
|
#[pymodule]
|
||||||
fn velopack(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
fn velopack(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||||
m.add_class::<VelopackError>()?;
|
m.add_class::<VelopackError>()?;
|
||||||
|
|
||||||
|
// auto-generated DTO's
|
||||||
m.add_class::<PyVelopackAsset>()?;
|
m.add_class::<PyVelopackAsset>()?;
|
||||||
m.add_class::<PyUpdateInfo>()?;
|
m.add_class::<PyUpdateInfo>()?;
|
||||||
|
m.add_class::<PyUpdateOptions>()?;
|
||||||
|
m.add_class::<PyVelopackLocatorConfig>()?;
|
||||||
|
|
||||||
|
// concrete classes
|
||||||
m.add_class::<VelopackAppWrapper>()?;
|
m.add_class::<VelopackAppWrapper>()?;
|
||||||
m.add_class::<UpdateManagerWrapper>()?;
|
m.add_class::<UpdateManagerWrapper>()?;
|
||||||
|
|
||||||
// add __version__ attribute
|
// add __version__ attribute
|
||||||
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
|
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// add __author__ attribute
|
// add __author__ attribute
|
||||||
m.add("__author__", env!("CARGO_PKG_AUTHORS"))?;
|
m.add("__author__", env!("CARGO_PKG_AUTHORS"))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
|
use pyo3::prelude::*;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use pyo3::prelude::*;
|
|
||||||
|
|
||||||
use velopack::{UpdateCheck, UpdateInfo, UpdateManager as VelopackUpdateManagerRust};
|
|
||||||
use velopack::sources::AutoSource;
|
use velopack::sources::AutoSource;
|
||||||
|
use velopack::{UpdateCheck, UpdateInfo, UpdateManager as VelopackUpdateManagerRust};
|
||||||
|
|
||||||
use crate::exceptions::VelopackError;
|
use crate::exceptions::VelopackError;
|
||||||
use crate::asset::PyUpdateInfo;
|
use crate::types::*;
|
||||||
|
|
||||||
#[pyclass(name = "UpdateManager")]
|
#[pyclass(name = "UpdateManager")]
|
||||||
pub struct UpdateManagerWrapper {
|
pub struct UpdateManagerWrapper {
|
||||||
@@ -17,88 +16,80 @@ pub struct UpdateManagerWrapper {
|
|||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl UpdateManagerWrapper {
|
impl UpdateManagerWrapper {
|
||||||
// for new, just take in a string, which is the source
|
// for new, just take in a string, which is the source
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new(source: String) -> PyResult<Self> {
|
#[pyo3(signature = (source, options = None, locator = None))]
|
||||||
let source = AutoSource::new(&source);
|
pub fn new(source: String, options: Option<PyUpdateOptions>, locator: Option<PyVelopackLocatorConfig>) -> PyResult<Self> {
|
||||||
// set myinner to a new VelopackUpdateManager with the source
|
let source = AutoSource::new(&source);
|
||||||
let inner = VelopackUpdateManagerRust::new(source, None, None)
|
// set myinner to a new VelopackUpdateManager with the source
|
||||||
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to create UpdateManager: {}", e)))?;
|
let inner = VelopackUpdateManagerRust::new(source, options.map(Into::into), locator.map(Into::into))
|
||||||
Ok(UpdateManagerWrapper {
|
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to create UpdateManager: {}", e)))?;
|
||||||
inner,
|
Ok(UpdateManagerWrapper { inner })
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// check_for_updates return update info indicating if updates are available
|
||||||
// check_for_updates return update info indicating if updates are available
|
|
||||||
/// This method checks for updates and returns update info if updates are available, None otherwise.
|
/// This method checks for updates and returns update info if updates are available, None otherwise.
|
||||||
pub fn check_for_updates(&mut self) -> PyResult<Option<PyUpdateInfo>> {
|
pub fn check_for_updates(&mut self) -> PyResult<Option<PyUpdateInfo>> {
|
||||||
let update_check = self.inner.check_for_updates()
|
let update_check =
|
||||||
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to check for updates: {}", e)))?;
|
self.inner.check_for_updates().map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to check for updates: {}", e)))?;
|
||||||
|
|
||||||
match update_check {
|
match update_check {
|
||||||
UpdateCheck::UpdateAvailable(updates) => {
|
UpdateCheck::UpdateAvailable(updates) => {
|
||||||
let py_updates = PyUpdateInfo::from(updates);
|
let py_updates = PyUpdateInfo::from(updates);
|
||||||
Ok(Some(py_updates))
|
Ok(Some(py_updates))
|
||||||
},
|
}
|
||||||
UpdateCheck::NoUpdateAvailable => {
|
UpdateCheck::NoUpdateAvailable => Ok(None),
|
||||||
Ok(None)
|
UpdateCheck::RemoteIsEmpty => Ok(None),
|
||||||
},
|
|
||||||
UpdateCheck::RemoteIsEmpty => {
|
|
||||||
Ok(None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
#[pyo3(signature = (update_info, progress_callback = None))]
|
||||||
|
pub fn download_updates(&mut self, update_info: &PyUpdateInfo, progress_callback: Option<PyObject>) -> PyResult<()> {
|
||||||
|
// Convert PyUpdateInfo back to rust UpdateInfo
|
||||||
|
let rust_update_info: UpdateInfo = update_info.clone().into();
|
||||||
|
|
||||||
#[pyo3(signature = (update_info, progress_callback = None))]
|
if let Some(callback) = progress_callback {
|
||||||
pub fn download_updates(&mut self, update_info: &PyUpdateInfo, progress_callback: Option<PyObject>) -> PyResult<()> {
|
// Create a channel for progress updates
|
||||||
// Convert PyUpdateInfo back to rust UpdateInfo
|
let (sender, receiver) = mpsc::channel::<i16>();
|
||||||
let rust_update_info: UpdateInfo = update_info.clone().into();
|
|
||||||
|
// Spawn a thread to handle progress updates
|
||||||
if let Some(callback) = progress_callback {
|
let progress_thread = thread::spawn(move || {
|
||||||
// Create a channel for progress updates
|
Python::with_gil(|py| {
|
||||||
let (sender, receiver) = mpsc::channel::<i16>();
|
while let Ok(progress) = receiver.recv() {
|
||||||
|
if let Err(e) = callback.call1(py, (progress,)) {
|
||||||
// Spawn a thread to handle progress updates
|
// Log error but continue - don't break the download
|
||||||
let progress_thread = thread::spawn(move || {
|
eprintln!("Progress callback error: {}", e);
|
||||||
Python::with_gil(|py| {
|
break;
|
||||||
while let Ok(progress) = receiver.recv() {
|
}
|
||||||
if let Err(e) = callback.call1(py, (progress,)) {
|
|
||||||
// Log error but continue - don't break the download
|
|
||||||
eprintln!("Progress callback error: {}", e);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
// Call download with the sender
|
||||||
// Call download with the sender
|
let result = self
|
||||||
let result = self.inner.download_updates(&rust_update_info, Some(sender))
|
.inner
|
||||||
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to download updates: {}", e)));
|
.download_updates(&rust_update_info, Some(sender))
|
||||||
|
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to download updates: {}", e)));
|
||||||
// Wait for the progress thread to finish
|
|
||||||
let _ = progress_thread.join();
|
// Wait for the progress thread to finish
|
||||||
|
let _ = progress_thread.join();
|
||||||
result.map(|_| ())
|
|
||||||
} else {
|
result.map(|_| ())
|
||||||
// No progress callback provided
|
} else {
|
||||||
self.inner.download_updates(&rust_update_info, None)
|
// No progress callback provided
|
||||||
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to download updates: {}", e)))
|
self.inner
|
||||||
|
.download_updates(&rust_update_info, None)
|
||||||
|
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to download updates: {}", e)))
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_updates_and_restart(&mut self, update_info: &PyUpdateInfo) -> PyResult<()> {
|
||||||
|
// Convert PyUpdateInfo back to rust UpdateInfo
|
||||||
|
let rust_update_info: UpdateInfo = update_info.clone().into();
|
||||||
|
|
||||||
|
self.inner
|
||||||
|
.apply_updates_and_restart(&rust_update_info)
|
||||||
|
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to apply updates and restart: {}", e)))
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_updates_and_restart(&mut self, update_info: &PyUpdateInfo) -> PyResult<()> {
|
|
||||||
// Convert PyUpdateInfo back to rust UpdateInfo
|
|
||||||
let rust_update_info: UpdateInfo = update_info.clone().into();
|
|
||||||
|
|
||||||
self.inner.apply_updates_and_restart(&rust_update_info)
|
|
||||||
.map_err(|e| PyErr::new::<VelopackError, _>(format!("Failed to apply updates and restart: {}", e)))
|
|
||||||
.map(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user