From 762421924c5a8cc0aa7b56d6d1aa9ae41b221dbc Mon Sep 17 00:00:00 2001 From: madonuko Date: Fri, 24 Jan 2025 00:11:31 +0800 Subject: [PATCH] feat(backend/custom): wip on making this actually work? --- Cargo.lock | 57 ++++++++++++-------------------------- Cargo.toml | 3 +- src/backend/custom.rs | 29 +++++++++++++++++-- src/main.rs | 4 +-- src/pages/installation.rs | 1 - src/pages/installcustom.rs | 6 ++-- src/util/fs.rs | 30 +++++++++++++++++++- src/util/macros.rs | 3 +- 8 files changed, 82 insertions(+), 51 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8adf54..6e828de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -395,25 +395,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-queue" version = "0.3.11" @@ -520,6 +501,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.13.0" @@ -671,6 +658,16 @@ dependencies = [ "xdg", ] +[[package]] +name = "fs-more" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbe0081d1a388d5115ce63bd6663559ae17e0d1d9657461fddf15d8e14e3badd" +dependencies = [ + "dunce", + "thiserror 1.0.69", +] + [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -2028,26 +2025,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - [[package]] name = "rdrand" version = "0.4.0" @@ -2069,6 +2046,7 @@ dependencies = [ "enum_dispatch", "format-bytes", "freedesktop-desktop-entry", + "fs-more", "gettext-rs", "glib-build-tools", "glob", @@ -2083,7 +2061,6 @@ dependencies = [ "os_pipe", "paste", "process_alive", - "rayon", "relm4", "scopeguard", "serde", diff --git a/Cargo.toml b/Cargo.toml index c7a7e28..0588e19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ serde_with = "3.9.0" uuid = { version = "1.10.0", features = ["serde"] } tiffin = { version = "0.3.2" } tracing-journald = "0.3.0" -rayon = "1.10.0" +# rayon = "1.10.0" process_alive = "0.1.1" crossbeam-queue = "0.3.11" strip-ansi-escapes = "0.2.0" @@ -52,6 +52,7 @@ format-bytes = "0.3.0" ipc-channel = { version = "0.19.0", features = ["async"] } which = "7.0.1" freedesktop-desktop-entry = "0.7.7" +fs-more = "0.8.0" [dependencies.os-detect] git = "https://github.com/FyraLabs/distinst" diff --git a/src/backend/custom.rs b/src/backend/custom.rs index 3110fa3..a1cfa27 100644 --- a/src/backend/custom.rs +++ b/src/backend/custom.rs @@ -2,8 +2,27 @@ use std::path::Component; use std::path::Path; use std::path::PathBuf; +use color_eyre::eyre::Context; + use super::install::InstallationState; +const DIR_COPY_OPTS: fs_more::directory::DirectoryCopyOptions = { + use fs_more::directory::{ + BrokenSymlinkBehaviour, CollidingSubDirectoryBehaviour, DestinationDirectoryRule, + DirectoryCopyDepthLimit, DirectoryCopyOptions, SymlinkBehaviour, + }; + use fs_more::file::CollidingFileBehaviour; + DirectoryCopyOptions { + destination_directory_rule: DestinationDirectoryRule::AllowNonEmpty { + colliding_file_behaviour: CollidingFileBehaviour::Overwrite, + colliding_subdirectory_behaviour: CollidingSubDirectoryBehaviour::Continue, + }, + copy_depth_limit: DirectoryCopyDepthLimit::Unlimited, + symlink_behaviour: SymlinkBehaviour::Keep, + broken_symlink_behaviour: BrokenSymlinkBehaviour::Keep, + } +}; + #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] pub struct MountTarget { #[doc(hidden)] @@ -100,11 +119,15 @@ pub fn install_custom( let copy_source = PathBuf::from(InstallationState::determine_copy_source()); if copy_source.is_file() { - // TODO: impl callback status progress - super::mksys::unsquash_copy(©_source, destroot, |_, _| {})?; + crate::stage!("Extracting files" { + super::mksys::unsquash_copy(©_source, destroot, |_, _| {})?; + }); } else { + crate::stage!("Copying files" { + fs_more::directory::copy_directory(©_source, destroot, DIR_COPY_OPTS).wrap_err("can't copy files")?; + }); tracing::info!(?copy_source, ?destroot, "Copying directory"); - crate::util::fs::copy_dir(©_source, destroot)?; + // crate::util::fs::copy_dir(©_source, destroot)?; } } diff --git a/src/main.rs b/src/main.rs index 81468c6..a8169bb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -133,10 +133,10 @@ impl SimpleComponent for AppModel { Page::Welcome => *model.welcome_page.widget(), Page::Destination => *model.destination_page.widget(), Page::InstallationType => *model.installation_type_page.widget(), - Page::Confirmation => *model.confirmation_page.widget(), - Page::Installation => *model.installation_page.widget(), Page::InstallDual => *model.install_dual_page.widget(), Page::InstallCustom => *model.install_custom_page.widget(), + Page::Confirmation => *model.confirmation_page.widget(), + Page::Installation => *model.installation_page.widget(), Page::Completed => *model.completed_page.widget(), Page::Failure => *model.failure_page.widget(), } diff --git a/src/pages/installation.rs b/src/pages/installation.rs index 1be5770..7196cf5 100644 --- a/src/pages/installation.rs +++ b/src/pages/installation.rs @@ -2,7 +2,6 @@ use crate::backend::install::InstallationMessage; use crate::prelude::*; use crate::{NavigationAction, INSTALLATION_STATE}; use color_eyre::Result; -use relm4::tokio::sync::broadcast::Receiver; use relm4::{Component, ComponentParts, ComponentSender}; use std::time::Duration; diff --git a/src/pages/installcustom.rs b/src/pages/installcustom.rs index edd4b97..11dbdf7 100644 --- a/src/pages/installcustom.rs +++ b/src/pages/installcustom.rs @@ -531,7 +531,7 @@ impl SimpleComponent for AddDialog { // HACK: relm4 doesn't perform the #[watch] until the UI is updated by the user // e.g. they typed something into the entry, then relm4 actually finally realize // it needs to set this as sensitive - // + // // therefore right here we just have relm4 default to a sensitivity before any UI trigs set_sensitive: !model.partition.is_empty(), }, @@ -721,7 +721,9 @@ impl AddDialog { // WARN: by design yes this is a memleak but we have no choice ctrl.detach_runtime(); ctrl.widget().set_transient_for(root_window.as_ref()); - libhelium::prelude::WindowExt::set_parent(ctrl.widget(), root_window.as_ref()); + libhelium::prelude::WindowExt::set_parent(ctrl.widget(), root_window.as_ref()); // FIXME: doubt if this actually works + // temporary hack is to use the gtk one instead + gtk::prelude::WidgetExt::set_parent(ctrl.widget(), &root_window.expect("no root window")); ctrl.widget().present(); ctrl } diff --git a/src/util/fs.rs b/src/util/fs.rs index f5d30b0..6e45dcf 100644 --- a/src/util/fs.rs +++ b/src/util/fs.rs @@ -28,8 +28,16 @@ pub fn exist_then_read_dir>( } } +/* pub fn copy_dir, Q: AsRef>(from: P, to: Q) -> color_eyre::Result<()> { use rayon::iter::{ParallelBridge, ParallelIterator}; + + // todo: use walkdir or something + // or https://crates.io/crates/dircpy + // or https://docs.rs/fs-more/latest/fs_more/directory/fn.copy_directory.html + // + // also parallelizing this is a bit of a waste, since we're doing a lot of IO, + // and we might mess with the dir order let to = to.as_ref(); std::fs::create_dir_all(to)?; @@ -47,7 +55,26 @@ pub fn copy_dir, Q: AsRef>(from: P, to: Q) -> color_eyre::R if metadata.is_dir() { copy_dir(dir_entry.path(), to)?; } else if metadata.is_symlink() { - let link = std::fs::read_link(dir_entry.path())?; + if dir_entry.path().exists() { + tracing::warn!( + ?dir_entry, + "File seems to already exist.. Removing anyway to make way for symlink" + ); + std::fs::remove_file(dir_entry.path()).map_err(|e| { + eyre!("can't remove file for symlink") + .note(format!("From : {}", dir_entry.path().display())) + .note(format!("To : {}", to.display())) + // .note(format!("Link : {}", link.display())) + .wrap_err(e) + })?; + } + let link = match std::fs::read_link(dir_entry.path()) { + Ok(link) => link, + Err(e) => { + tracing::warn!(path=?dir_entry.path(), ?e, "link does not exist, skipping"); + return Ok(()); + } + }; std::os::unix::fs::symlink(&link, &to).map_err(|e| { eyre!("can't symlink") .note(format!("From : {}", dir_entry.path().display())) @@ -66,6 +93,7 @@ pub fn copy_dir, Q: AsRef>(from: P, to: Q) -> color_eyre::R Ok(()) }) } +*/ /// Get partition number from partition path /// diff --git a/src/util/macros.rs b/src/util/macros.rs index 701efc8..17ae60e 100644 --- a/src/util/macros.rs +++ b/src/util/macros.rs @@ -8,8 +8,9 @@ macro_rules! stage { let sender = m.lock().unwrap(); // Then we are in a non-interactive install, which means we export IPC // to stdout + let status_localized = gettextrs::gettext($s).to_owned(); let install_status = - $crate::backend::install::InstallationMessage::Status($s.to_owned()); + $crate::backend::install::InstallationMessage::Status(status_localized); sender.send(install_status).unwrap(); }