Implement rust linux functions stubs

This commit is contained in:
Caelan
2024-01-10 11:15:18 +00:00
parent a72c313405
commit fba9689bab
7 changed files with 134 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -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

View File

@@ -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(&current_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"), &current_dir)?;
std::fs::set_permissions(&current_dir, <std::fs::Permissions as std::os::unix::fs::PermissionsExt>::from_mode(0o755))?;
info!("AppImage extracted successfully to {}", &current_dir);
Ok(())
}
#[cfg(not(target_os = "linux"))]
{
bundle.extract_lib_contents_to_path(&current_dir, |_| {})
}
} else {
bail!("No bundle could be loaded.");
}

View File

@@ -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
}
}
}

View File

@@ -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,
})
}

View File

@@ -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(());

View File

@@ -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.")
}