mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
Implement rust linux functions stubs
This commit is contained in:
BIN
examples/AvaloniaCrossPlat/Velopack.png
Normal file
BIN
examples/AvaloniaCrossPlat/Velopack.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
@@ -31,4 +31,4 @@ echo "class Const { public const string RELEASES_DIR = @\"{REPLACE_ME}\"; } " >
|
||||
echo "Const.cs file reset"
|
||||
|
||||
echo "Building Velopack Release v$version"
|
||||
"$(dirname "$0")/../../build/Debug/net8.0/vpk" pack -u AvaloniaCrossPlat -v "$version" -o "$releasesDir" -p "$(dirname "$0")/publish" -i Velopack.icns
|
||||
"$(dirname "$0")/../../build/Debug/net8.0/vpk" pack -u AvaloniaCrossPlat -v "$version" -o "$releasesDir" -p "$(dirname "$0")/publish" -i Velopack.png
|
||||
@@ -106,7 +106,19 @@ fn apply_package_impl<'a>(
|
||||
let current_dir = app.get_current_path(&root_path);
|
||||
if let Err(e) = shared::replace_dir_with_rollback(current_dir.clone(), || {
|
||||
if let Some(bundle) = package_bundle.take() {
|
||||
bundle.extract_lib_contents_to_path(¤t_dir, |_| {})
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
// on linux, the current "dir" is actually an AppImage file which we need to replace.
|
||||
info!("Extracting AppImage");
|
||||
bundle.extract_zip_predicate_to_path(|z| z.ends_with(".AppImage"), ¤t_dir)?;
|
||||
std::fs::set_permissions(¤t_dir, <std::fs::Permissions as std::os::unix::fs::PermissionsExt>::from_mode(0o755))?;
|
||||
info!("AppImage extracted successfully to {}", ¤t_dir);
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
bundle.extract_lib_contents_to_path(¤t_dir, |_| {})
|
||||
}
|
||||
} else {
|
||||
bail!("No bundle could be loaded.");
|
||||
}
|
||||
|
||||
@@ -392,13 +392,21 @@ impl Manifest {
|
||||
#[cfg(target_os = "linux")]
|
||||
impl Manifest {
|
||||
pub fn get_packages_path(&self, _root_path: &PathBuf) -> String {
|
||||
todo!();
|
||||
let tmp = format!("/var/tmp/velopack/{}/packages", self.id);
|
||||
let p = Path::new(&tmp);
|
||||
if !p.exists() {
|
||||
fs::create_dir_all(p).unwrap();
|
||||
}
|
||||
p.to_string_lossy().to_string()
|
||||
}
|
||||
pub fn get_current_path(&self, root_path: &PathBuf) -> String {
|
||||
todo!();
|
||||
}
|
||||
pub fn get_nuspec_path(&self, root_path: &PathBuf) -> String {
|
||||
todo!();
|
||||
pub fn get_current_path(&self, _root_path: &PathBuf) -> String {
|
||||
let path = std::env::var("APPIMAGE").unwrap();
|
||||
if !Path::new(&path).exists() {
|
||||
error!("APPIMAGE is not set, or does not point to an existing file: {}", path);
|
||||
String::new()
|
||||
} else {
|
||||
path
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use dialog::{DialogBox, Choice};
|
||||
use super::dialogs_const::*;
|
||||
use anyhow::{Result, anyhow};
|
||||
use anyhow::{anyhow, Result};
|
||||
use dialog::{Choice, DialogBox};
|
||||
|
||||
pub fn generate_alert(title: &str, header: Option<&str>, body: &str, _ok_text: Option<&str>, _btns: DialogButton, _ico: DialogIcon) -> Result<()> {
|
||||
let mut body = body.to_string();
|
||||
@@ -8,8 +8,7 @@ pub fn generate_alert(title: &str, header: Option<&str>, body: &str, _ok_text: O
|
||||
body = format!("{}\n{}", h, body);
|
||||
}
|
||||
|
||||
dialog::Message::new(body).title(title).show()
|
||||
.map_err(|e| anyhow!("Failed to open dialog ({})", e))?;
|
||||
dialog::Message::new(body).title(title).show().map_err(|e| anyhow!("Failed to open dialog ({})", e))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -19,12 +18,11 @@ pub fn generate_confirm(title: &str, header: Option<&str>, body: &str, _ok_text:
|
||||
body = format!("{}\n{}", h, body);
|
||||
}
|
||||
|
||||
let result = dialog::Question::new(body).title(title).show()
|
||||
.map_err(|e| anyhow!("Failed to open dialog ({})", e))?;
|
||||
let result = dialog::Question::new(body).title(title).show().map_err(|e| anyhow!("Failed to open dialog ({})", e))?;
|
||||
|
||||
Ok(match result {
|
||||
Choice::Cancel => DialogResult::Cancel,
|
||||
Choice::No => DialogResult::No,
|
||||
Choice::Yes => DialogResult::Yes,
|
||||
Choice::No => DialogResult::Cancel,
|
||||
Choice::Yes => DialogResult::Ok,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ pub fn replace_dir_with_rollback<F, T, P: AsRef<Path>>(path: P, op: F) -> Result
|
||||
where
|
||||
F: FnOnce() -> Result<T>,
|
||||
{
|
||||
let path = path.as_ref().to_string_lossy().to_string();
|
||||
let path = path.as_ref();
|
||||
let is_dir = path.is_dir();
|
||||
let path = path.to_string_lossy().to_string();
|
||||
let mut path_renamed = String::new();
|
||||
|
||||
if !is_dir_empty(&path) {
|
||||
@@ -20,8 +22,11 @@ where
|
||||
retry_io(|| fs::rename(&path, &path_renamed)).map_err(|z| anyhow!("Failed to rename directory '{}' to '{}' ({}).", path, path_renamed, z))?;
|
||||
}
|
||||
|
||||
remove_dir_all::ensure_empty_dir(&path).map_err(|z| anyhow!("Failed to create clean directory '{}' ({}).", path, z))?;
|
||||
if is_dir {
|
||||
remove_dir_all::ensure_empty_dir(&path).map_err(|z| anyhow!("Failed to create clean directory '{}' ({}).", path, z))?;
|
||||
}
|
||||
|
||||
info!("Running rollback protected operation...");
|
||||
if let Err(e) = op() {
|
||||
// install failed, rollback if possible
|
||||
warn!("Rolling back installation... (error was: {:?})", e);
|
||||
@@ -42,9 +47,15 @@ where
|
||||
} else {
|
||||
// install successful, remove rollback directory if exists
|
||||
if !path_renamed.is_empty() {
|
||||
debug!("Removing rollback directory '{}'.", path_renamed);
|
||||
if let Err(ex) = super::retry_io(|| fs::remove_dir_all(&path_renamed)) {
|
||||
warn!("Failed to remove directory '{}' ({}).", path_renamed, ex);
|
||||
debug!("Removing rollback path '{}'.", path_renamed);
|
||||
if is_dir {
|
||||
if let Err(ex) = super::retry_io(|| fs::remove_dir_all(&path_renamed)) {
|
||||
warn!("Failed to remove rollback directory '{}' ({}).", path_renamed, ex);
|
||||
}
|
||||
} else {
|
||||
if let Err(ex) = super::retry_io(|| fs::remove_file(&path_renamed)) {
|
||||
warn!("Failed to remove rollback file '{}' ({}).", path_renamed, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use crate::shared::bundle;
|
||||
|
||||
use super::bundle::Manifest;
|
||||
use crate::shared::bundle;
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::{path::Path, path::PathBuf, process::Command as Process, time::Duration};
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
pub fn wait_for_parent_to_exit(ms_to_wait: u32) -> Result<()> {
|
||||
let id = std::os::unix::process::parent_id();
|
||||
@@ -20,18 +22,92 @@ pub fn wait_for_parent_to_exit(ms_to_wait: u32) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn force_stop_package<P: AsRef<Path>>(root_dir: P) -> Result<()> {
|
||||
todo!();
|
||||
pub fn copy_own_fd_to_file(output_path: &str) -> Result<()> {
|
||||
let path = std::ffi::CString::new("/proc/self/exe")?;
|
||||
let fd = unsafe { libc::open(path.as_ptr(), libc::O_RDONLY) };
|
||||
let result = copy_fd_to_file(fd, &output_path);
|
||||
unsafe { libc::close(fd) };
|
||||
result?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start_package<P: AsRef<Path>>(_app: &Manifest, root_dir: P, exe_args: Option<Vec<&str>>, set_env: Option<&str>) -> Result<()> {
|
||||
todo!();
|
||||
fn copy_fd_to_file(fd: i32, output_path: &str) -> Result<()> {
|
||||
// SAFETY: Assuming the FD is valid and open for reading
|
||||
let mut source_file = unsafe { File::from_raw_fd(fd) };
|
||||
let mut target_file = File::create(output_path)?;
|
||||
|
||||
// Buffer to hold data while copying
|
||||
let mut buffer = [0; 4096];
|
||||
|
||||
loop {
|
||||
let bytes_read = source_file.read(&mut buffer)?;
|
||||
if bytes_read == 0 {
|
||||
break; // End of file reached
|
||||
}
|
||||
target_file.write_all(&buffer[..bytes_read])?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn force_stop_package<P: AsRef<Path>>(_root_dir: P) -> Result<()> {
|
||||
// not supported on linux / no-op
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn start_package<P: AsRef<Path>>(_app: &Manifest, _root_dir: P, exe_args: Option<Vec<&str>>, set_env: Option<&str>) -> Result<()> {
|
||||
let path = std::env::var("APPIMAGE")?;
|
||||
|
||||
if !Path::new(&path).exists() {
|
||||
bail!("APPIMAGE is not set, or does not point to an existing file: {}", path);
|
||||
}
|
||||
|
||||
info!("APPIMAGE: {}", path);
|
||||
if !Path::new(&path).exists() {
|
||||
bail!("AppImage does not exist!");
|
||||
}
|
||||
|
||||
let mut cmd = Process::new(path);
|
||||
if let Some(args) = exe_args {
|
||||
cmd.args(args);
|
||||
}
|
||||
if let Some(env) = set_env {
|
||||
cmd.env(env, "true");
|
||||
}
|
||||
cmd.spawn().map_err(|z| anyhow!("Failed to start_package ({}).", z))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn detect_manifest_from_update_path(update_exe: &PathBuf) -> Result<(PathBuf, Manifest)> {
|
||||
todo!();
|
||||
let mut manifest_path = update_exe.clone();
|
||||
manifest_path.pop();
|
||||
manifest_path.push("sq.version");
|
||||
let manifest = load_manifest(&manifest_path)?;
|
||||
|
||||
let my_path = std::env::current_exe()?;
|
||||
let my_path = my_path.to_string_lossy();
|
||||
let app_idx = my_path.find("/usr/bin/");
|
||||
if app_idx.is_none() {
|
||||
bail!("Unable to find /usr/bin/ directory in path: {}", my_path);
|
||||
}
|
||||
|
||||
let root_dir = &my_path[..app_idx.unwrap()];
|
||||
|
||||
debug!("Detected Root: {}", root_dir);
|
||||
debug!("Detected AppId: {}", manifest.id);
|
||||
Ok((Path::new(&root_dir).to_path_buf(), manifest))
|
||||
}
|
||||
|
||||
pub fn detect_current_manifest() -> Result<(PathBuf, Manifest)> {
|
||||
todo!();
|
||||
let me = std::env::current_exe()?;
|
||||
detect_manifest_from_update_path(&me)
|
||||
}
|
||||
|
||||
fn load_manifest(nuspec_path: &PathBuf) -> Result<Manifest> {
|
||||
if Path::new(&nuspec_path).exists() {
|
||||
if let Ok(nuspec) = super::retry_io(|| std::fs::read_to_string(&nuspec_path)) {
|
||||
return Ok(bundle::read_manifest_from_string(&nuspec)?);
|
||||
}
|
||||
}
|
||||
bail!("Unable to read nuspec file in current directory.")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user