Compare commits
No commits in common. "8a65313039a40030dd6f6f79ea77fad828028a95" and "87ccc806026b2f9debccb8b59dfab2d92380ad4a" have entirely different histories.
8a65313039
...
87ccc80602
7 changed files with 32 additions and 257 deletions
|
|
@ -22,7 +22,6 @@ use ratatui::{
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use strum::Display;
|
use strum::Display;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
use super::Component;
|
use super::Component;
|
||||||
use crate::{action::Action, config::Config};
|
use crate::{action::Action, config::Config};
|
||||||
|
|
@ -65,7 +64,6 @@ impl Component for Popup {
|
||||||
match action {
|
match action {
|
||||||
Action::DismissPopup => self.popup_text.clear(),
|
Action::DismissPopup => self.popup_text.clear(),
|
||||||
Action::DisplayPopup(new_type, new_text) => {
|
Action::DisplayPopup(new_type, new_text) => {
|
||||||
info!("Show Popup ({new_type}): {new_text}");
|
|
||||||
self.popup_type = new_type;
|
self.popup_type = new_type;
|
||||||
self.popup_text = format!("\n{new_text}");
|
self.popup_text = format!("\n{new_text}");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,12 +96,6 @@ pub fn get_disk_description_right(
|
||||||
line_colors,
|
line_colors,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if disk.parts_description.is_empty() {
|
|
||||||
description.push(DVLine {
|
|
||||||
line_parts: vec![String::from("-None-")],
|
|
||||||
line_colors: vec![Color::Reset],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
description
|
description
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,6 @@ use crate::system::disk::{
|
||||||
|
|
||||||
static DEFAULT_MAX_DISKS: usize = 8;
|
static DEFAULT_MAX_DISKS: usize = 8;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub enum FormatUseCase {
|
|
||||||
ApplyWimImage,
|
|
||||||
Clone,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RegexList {
|
pub struct RegexList {
|
||||||
detail_all_disks: OnceLock<Regex>,
|
detail_all_disks: OnceLock<Regex>,
|
||||||
detail_disk: OnceLock<Regex>,
|
detail_disk: OnceLock<Regex>,
|
||||||
|
|
@ -211,11 +205,7 @@ pub fn get_partitions(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn build_dest_format_script(
|
pub fn build_dest_format_script(disk_id: usize, part_type: &PartitionTableType) -> String {
|
||||||
disk_id: usize,
|
|
||||||
part_type: &PartitionTableType,
|
|
||||||
format_use_case: FormatUseCase,
|
|
||||||
) -> String {
|
|
||||||
let disk_id = format!("{disk_id}");
|
let disk_id = format!("{disk_id}");
|
||||||
let mut script = vec!["automount enable noerr", "select disk {disk_id}", "clean"];
|
let mut script = vec!["automount enable noerr", "select disk {disk_id}", "clean"];
|
||||||
match part_type {
|
match part_type {
|
||||||
|
|
@ -231,10 +221,6 @@ pub fn build_dest_format_script(
|
||||||
script.push("format fs=ntfs quick label=System");
|
script.push("format fs=ntfs quick label=System");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if format_use_case == FormatUseCase::ApplyWimImage {
|
|
||||||
script.push("create partition primary");
|
|
||||||
script.push("format fs=ntfs quick label=Windows");
|
|
||||||
}
|
|
||||||
script.join("\r\n").replace("{disk_id}", &disk_id)
|
script.join("\r\n").replace("{disk_id}", &disk_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,7 @@ use core::{
|
||||||
line::{DVLine, get_disk_description_right, get_part_description},
|
line::{DVLine, get_disk_description_right, get_part_description},
|
||||||
state::Mode,
|
state::Mode,
|
||||||
system::{
|
system::{
|
||||||
boot,
|
boot, cpu::get_cpu_name, disk::PartitionTableType, diskpart::build_dest_format_script,
|
||||||
cpu::get_cpu_name,
|
|
||||||
disk::PartitionTableType,
|
|
||||||
diskpart::{FormatUseCase, build_dest_format_script},
|
|
||||||
drivers,
|
drivers,
|
||||||
},
|
},
|
||||||
tasks::{Task, TaskResult, TaskType, Tasks},
|
tasks::{Task, TaskResult, TaskType, Tasks},
|
||||||
|
|
@ -212,8 +209,7 @@ impl App {
|
||||||
&& let Some(disk) = disk_list.get(disk_index)
|
&& let Some(disk) = disk_list.get(disk_index)
|
||||||
{
|
{
|
||||||
let table_type = self.state.table_type.clone().unwrap();
|
let table_type = self.state.table_type.clone().unwrap();
|
||||||
let diskpart_script =
|
let diskpart_script = build_dest_format_script(disk.id, &table_type);
|
||||||
build_dest_format_script(disk.id, &table_type, FormatUseCase::Clone);
|
|
||||||
self.tasks.add(TaskType::Diskpart(diskpart_script));
|
self.tasks.add(TaskType::Diskpart(diskpart_script));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,20 +26,12 @@ use core::{
|
||||||
config::Config,
|
config::Config,
|
||||||
line::{DVLine, get_disk_description_right},
|
line::{DVLine, get_disk_description_right},
|
||||||
state::Mode,
|
state::Mode,
|
||||||
system::{
|
system::{cpu::get_cpu_name, disk::PartitionTableType, drivers},
|
||||||
boot,
|
tasks::{TaskType, Tasks},
|
||||||
cpu::get_cpu_name,
|
|
||||||
disk::PartitionTableType,
|
|
||||||
diskpart::{FormatUseCase, build_dest_format_script},
|
|
||||||
drivers,
|
|
||||||
},
|
|
||||||
tasks::{Task, TaskResult, TaskType, Tasks},
|
|
||||||
tui::{Event, Tui},
|
tui::{Event, Tui},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
|
||||||
iter::zip,
|
iter::zip,
|
||||||
path::PathBuf,
|
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -119,20 +111,20 @@ impl App {
|
||||||
Mode::SelectWinSource => Mode::SelectWinImage,
|
Mode::SelectWinSource => Mode::SelectWinImage,
|
||||||
Mode::SelectWinImage => Mode::SetUserName,
|
Mode::SelectWinImage => Mode::SetUserName,
|
||||||
Mode::SetUserName => Mode::Confirm,
|
Mode::SetUserName => Mode::Confirm,
|
||||||
Mode::Confirm => Mode::PreClone,
|
Mode::Confirm => Mode::Process, // i.e. format, apply, etc
|
||||||
Mode::PreClone => Mode::Clone,
|
Mode::Process | Mode::Done => Mode::Done,
|
||||||
Mode::Clone => Mode::PostClone,
|
|
||||||
Mode::PostClone | Mode::Done => Mode::Done,
|
|
||||||
Mode::Failed => Mode::Failed,
|
Mode::Failed => Mode::Failed,
|
||||||
// Invalid States
|
// Invalid States
|
||||||
Mode::BootDiags
|
Mode::BootDiags
|
||||||
| Mode::BootScan
|
| Mode::BootScan
|
||||||
| Mode::BootSetup
|
| Mode::BootSetup
|
||||||
|
| Mode::Clone
|
||||||
| Mode::DiagMenu
|
| Mode::DiagMenu
|
||||||
| Mode::InjectDrivers
|
| Mode::InjectDrivers
|
||||||
| Mode::LogView
|
| Mode::LogView
|
||||||
| Mode::PEMenu
|
| Mode::PEMenu
|
||||||
| Mode::Process
|
| Mode::PreClone
|
||||||
|
| Mode::PostClone
|
||||||
| Mode::SelectParts
|
| Mode::SelectParts
|
||||||
| Mode::SetBootMode => panic!("This shouldn't happen?"),
|
| Mode::SetBootMode => panic!("This shouldn't happen?"),
|
||||||
}
|
}
|
||||||
|
|
@ -147,126 +139,6 @@ impl App {
|
||||||
// self.action_tx
|
// self.action_tx
|
||||||
// .send(Action::DisplayPopup(popup::Type::Info, String::from("...")))?;
|
// .send(Action::DisplayPopup(popup::Type::Info, String::from("...")))?;
|
||||||
// }
|
// }
|
||||||
Mode::PreClone => {
|
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
|
||||||
popup::Type::Info,
|
|
||||||
String::from("Formatting destination disk"),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// Get System32 path
|
|
||||||
let system32 = get_system32_path(&self.action_tx);
|
|
||||||
|
|
||||||
// (Re)Enable volume mounting
|
|
||||||
self.tasks.add(TaskType::CommandWait(
|
|
||||||
PathBuf::from(format!("{system32}/mountvol.exe")),
|
|
||||||
vec![String::from("/e")],
|
|
||||||
));
|
|
||||||
|
|
||||||
// Build Diskpart script to format destination disk
|
|
||||||
let disk_list = self.state.disk_list.lock().unwrap();
|
|
||||||
if let Some(disk_index) = self.state.disk_index_dest
|
|
||||||
&& let Some(disk) = disk_list.get(disk_index)
|
|
||||||
{
|
|
||||||
let table_type = self.state.table_type.clone().unwrap();
|
|
||||||
let diskpart_script = build_dest_format_script(
|
|
||||||
disk.id,
|
|
||||||
&table_type,
|
|
||||||
FormatUseCase::ApplyWimImage,
|
|
||||||
);
|
|
||||||
self.tasks.add(TaskType::Diskpart(diskpart_script));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update drive letters
|
|
||||||
self.tasks.add(TaskType::Sleep);
|
|
||||||
if let Some(dest_index) = self.state.disk_index_dest {
|
|
||||||
self.tasks.add(TaskType::UpdateDestDisk(dest_index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mode::Clone => {
|
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
|
||||||
popup::Type::Info,
|
|
||||||
String::from("Applying Image"),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// Get wimlib-imagex path
|
|
||||||
let program_files = PathBuf::from(get_program_files_path(&self.action_tx));
|
|
||||||
let wimlib_imagex = program_files.join("wimlib\\wimlib-imagex.exe");
|
|
||||||
|
|
||||||
// Get image info
|
|
||||||
let wim_sources = self.state.wim_sources.lock().unwrap();
|
|
||||||
let wim_file = wim_sources.get_file(self.state.wim_file_index.unwrap());
|
|
||||||
let wim_index = format!("{}", self.state.wim_image_index.unwrap());
|
|
||||||
|
|
||||||
// Add actions
|
|
||||||
let disk_list = self.state.disk_list.lock().unwrap();
|
|
||||||
if let Some(disk_index) = self.state.disk_index_dest
|
|
||||||
&& let Some(disk) = disk_list.get(disk_index)
|
|
||||||
{
|
|
||||||
let num_parts = disk.parts.len();
|
|
||||||
let dest_path = format!("{}:\\", disk.get_part_letter(num_parts - 1));
|
|
||||||
self.tasks.add(TaskType::CommandWait(
|
|
||||||
wimlib_imagex,
|
|
||||||
vec![String::from("apply"), wim_file.path, wim_index, dest_path],
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mode::PostClone => {
|
|
||||||
self.action_tx.send(Action::DisplayPopup(
|
|
||||||
popup::Type::Info,
|
|
||||||
String::from("Updating boot configuration"),
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// Get System32 path
|
|
||||||
let system32 = get_system32_path(&self.action_tx);
|
|
||||||
|
|
||||||
// Add actions
|
|
||||||
let disk_list = self.state.disk_list.lock().unwrap();
|
|
||||||
if let Some(disk_index) = self.state.disk_index_dest
|
|
||||||
&& let Some(disk) = disk_list.get(disk_index)
|
|
||||||
{
|
|
||||||
let table_type = self.state.table_type.clone().unwrap();
|
|
||||||
let letter_boot = disk.get_part_letter(0);
|
|
||||||
let letter_os =
|
|
||||||
disk.get_part_letter(match self.state.table_type.clone().unwrap() {
|
|
||||||
PartitionTableType::Guid => 2,
|
|
||||||
PartitionTableType::Legacy => 1,
|
|
||||||
});
|
|
||||||
info!("PostClone // Disk: {disk:?}");
|
|
||||||
info!("\t\tBoot letter: {letter_boot}");
|
|
||||||
info!("\t\tOS letter: {letter_os}");
|
|
||||||
|
|
||||||
// Safety check
|
|
||||||
if letter_boot.is_empty() || letter_os.is_empty() {
|
|
||||||
self.action_tx.send(Action::Error(String::from(
|
|
||||||
"ERROR\n\n\nFailed to get drive letters for the destination",
|
|
||||||
)))?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create boot files
|
|
||||||
for task in boot::configure_disk(
|
|
||||||
&letter_boot,
|
|
||||||
&letter_os,
|
|
||||||
boot::SafeMode::Enable,
|
|
||||||
&system32,
|
|
||||||
&table_type,
|
|
||||||
) {
|
|
||||||
self.tasks.add(task);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inject driver(s) (if selected)
|
|
||||||
if let Some(driver) = &self.state.driver {
|
|
||||||
if let Ok(task) = boot::inject_driver(driver, &letter_os, &system32) {
|
|
||||||
self.tasks.add(task);
|
|
||||||
} else {
|
|
||||||
self.action_tx.send(Action::Error(format!(
|
|
||||||
"Failed to inject driver:\n{}",
|
|
||||||
driver.name
|
|
||||||
)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Mode::ScanDisks => {
|
Mode::ScanDisks => {
|
||||||
self.state.reset_all();
|
self.state.reset_all();
|
||||||
if self.tasks.idle() {
|
if self.tasks.idle() {
|
||||||
|
|
@ -286,7 +158,7 @@ impl App {
|
||||||
&& let Some(index) = self.state.wim_image_index
|
&& let Some(index) = self.state.wim_image_index
|
||||||
{
|
{
|
||||||
let image = wim_sources.get_file(index);
|
let image = wim_sources.get_file(index);
|
||||||
if image.is_backup {
|
if !image.is_setup {
|
||||||
self.action_tx.send(Action::NextScreen)?;
|
self.action_tx.send(Action::NextScreen)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,9 +261,7 @@ impl App {
|
||||||
Action::Tick => {
|
Action::Tick => {
|
||||||
self.last_tick_key_events.drain(..);
|
self.last_tick_key_events.drain(..);
|
||||||
// Check background task(s)
|
// Check background task(s)
|
||||||
if let Some(task) = self.tasks.poll()? {
|
self.tasks.poll()?;
|
||||||
self.handle_task(&task)?;
|
|
||||||
}
|
|
||||||
if let Ok(mut wim_sources) = self.state.wim_sources.lock() {
|
if let Ok(mut wim_sources) = self.state.wim_sources.lock() {
|
||||||
wim_sources.poll();
|
wim_sources.poll();
|
||||||
}
|
}
|
||||||
|
|
@ -447,11 +317,6 @@ impl App {
|
||||||
self.action_tx.send(Action::DismissPopup)?;
|
self.action_tx.send(Action::DismissPopup)?;
|
||||||
self.action_tx.send(Action::SetMode(next_mode))?;
|
self.action_tx.send(Action::SetMode(next_mode))?;
|
||||||
}
|
}
|
||||||
Action::DisplayPopup(ref popup_type, ref _popup_text) => {
|
|
||||||
if *popup_type == popup::Type::Error {
|
|
||||||
self.action_tx.send(Action::SetMode(Mode::Failed))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Action::PrevScreen => match self.cur_mode {
|
Action::PrevScreen => match self.cur_mode {
|
||||||
Mode::SelectTableType => {
|
Mode::SelectTableType => {
|
||||||
self.action_tx.send(Action::SetMode(Mode::SelectDisks))?;
|
self.action_tx.send(Action::SetMode(Mode::SelectDisks))?;
|
||||||
|
|
@ -540,39 +405,6 @@ impl App {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_task(&mut self, task: &Task) -> Result<()> {
|
|
||||||
match task.task_type {
|
|
||||||
TaskType::CommandWait(_, _) | TaskType::Diskpart(_) => {
|
|
||||||
// Check result
|
|
||||||
if let Some(result) = &task.result {
|
|
||||||
match result {
|
|
||||||
TaskResult::Error(msg) => {
|
|
||||||
self.action_tx
|
|
||||||
.send(Action::Error(format!("{} Failed: {msg}", task.task_type)))?;
|
|
||||||
}
|
|
||||||
TaskResult::Output(stdout, stderr, success) => {
|
|
||||||
if !success {
|
|
||||||
let msg = if !stdout.is_empty() {
|
|
||||||
stdout.clone()
|
|
||||||
} else if !stderr.is_empty() {
|
|
||||||
stderr.clone()
|
|
||||||
} else {
|
|
||||||
String::from("Unknown Error")
|
|
||||||
};
|
|
||||||
self.action_tx.send(Action::Error(format!(
|
|
||||||
"{} Failed: {msg}",
|
|
||||||
task.task_type
|
|
||||||
)))?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render(&mut self, tui: &mut Tui) -> Result<()> {
|
fn render(&mut self, tui: &mut Tui) -> Result<()> {
|
||||||
tui.draw(|frame| {
|
tui.draw(|frame| {
|
||||||
if let [header, _body, footer, center, left, right, username, popup] =
|
if let [header, _body, footer, center, left, right, username, popup] =
|
||||||
|
|
@ -594,9 +426,7 @@ impl App {
|
||||||
|
|
||||||
fn build_footer_string(cur_mode: Mode) -> String {
|
fn build_footer_string(cur_mode: Mode) -> String {
|
||||||
match cur_mode {
|
match cur_mode {
|
||||||
Mode::Home | Mode::ScanDisks | Mode::PreClone | Mode::Clone | Mode::PostClone => {
|
Mode::Home | Mode::ScanDisks => String::from("(q) to quit"),
|
||||||
String::from("(q) to quit")
|
|
||||||
}
|
|
||||||
Mode::InstallDrivers => String::from("(Enter) to select / (q) to quit"),
|
Mode::InstallDrivers => String::from("(Enter) to select / (q) to quit"),
|
||||||
Mode::SelectDisks => String::from(
|
Mode::SelectDisks => String::from(
|
||||||
"(Enter) to select / / (i) to install driver / (r) to rescan / (q) to quit",
|
"(Enter) to select / / (i) to install driver / (r) to rescan / (q) to quit",
|
||||||
|
|
@ -610,16 +440,18 @@ fn build_footer_string(cur_mode: Mode) -> String {
|
||||||
),
|
),
|
||||||
Mode::SetUserName => String::from("(Enter) to continue / (Esc) to go back"),
|
Mode::SetUserName => String::from("(Enter) to continue / (Esc) to go back"),
|
||||||
Mode::Confirm => String::from("(Enter) to confirm / (b) to go back / (q) to quit"),
|
Mode::Confirm => String::from("(Enter) to confirm / (b) to go back / (q) to quit"),
|
||||||
Mode::Done | Mode::Failed => String::from("(Enter) or (q) to quit"),
|
Mode::Done | Mode::Failed | Mode::Process => String::from("(Enter) or (q) to quit"),
|
||||||
// Invalid States
|
// Invalid States
|
||||||
Mode::BootDiags
|
Mode::BootDiags
|
||||||
| Mode::BootScan
|
| Mode::BootScan
|
||||||
| Mode::BootSetup
|
| Mode::BootSetup
|
||||||
|
| Mode::Clone
|
||||||
| Mode::DiagMenu
|
| Mode::DiagMenu
|
||||||
| Mode::InjectDrivers
|
| Mode::InjectDrivers
|
||||||
| Mode::LogView
|
| Mode::LogView
|
||||||
| Mode::PEMenu
|
| Mode::PEMenu
|
||||||
| Mode::Process
|
| Mode::PreClone
|
||||||
|
| Mode::PostClone
|
||||||
| Mode::SelectParts
|
| Mode::SelectParts
|
||||||
| Mode::SetBootMode => panic!("This shouldn't happen?"),
|
| Mode::SetBootMode => panic!("This shouldn't happen?"),
|
||||||
}
|
}
|
||||||
|
|
@ -643,9 +475,15 @@ fn build_left_items(app: &App) -> Action {
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|driver| items.push(driver.to_string()));
|
.for_each(|driver| items.push(driver.to_string()));
|
||||||
}
|
}
|
||||||
|
Mode::Process => {
|
||||||
|
select_type = SelectionType::Loop;
|
||||||
|
title = String::from("Processing");
|
||||||
|
// TODO: FIXME
|
||||||
|
}
|
||||||
Mode::ScanWinSources => {
|
Mode::ScanWinSources => {
|
||||||
select_type = SelectionType::Loop;
|
select_type = SelectionType::Loop;
|
||||||
title = String::from("Scanning");
|
title = String::from("Scanning");
|
||||||
|
// TODO: FIXME
|
||||||
}
|
}
|
||||||
Mode::SelectWinSource => {
|
Mode::SelectWinSource => {
|
||||||
select_type = SelectionType::One;
|
select_type = SelectionType::One;
|
||||||
|
|
@ -701,7 +539,6 @@ fn build_left_items(app: &App) -> Action {
|
||||||
| Mode::BootScan
|
| Mode::BootScan
|
||||||
| Mode::BootSetup
|
| Mode::BootSetup
|
||||||
| Mode::DiagMenu
|
| Mode::DiagMenu
|
||||||
| Mode::Process
|
|
||||||
| Mode::InjectDrivers
|
| Mode::InjectDrivers
|
||||||
| Mode::LogView
|
| Mode::LogView
|
||||||
| Mode::PEMenu
|
| Mode::PEMenu
|
||||||
|
|
@ -816,12 +653,7 @@ fn build_right_items(app: &App) -> Action {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Mode::SelectWinImage
|
Mode::SelectWinImage | Mode::SetUserName | Mode::Confirm => {
|
||||||
| Mode::SetUserName
|
|
||||||
| Mode::Confirm
|
|
||||||
| Mode::PreClone
|
|
||||||
| Mode::Clone
|
|
||||||
| Mode::PostClone => {
|
|
||||||
info!("Building right items for: {:?}", &app.cur_mode);
|
info!("Building right items for: {:?}", &app.cur_mode);
|
||||||
let wim_file;
|
let wim_file;
|
||||||
if let Ok(wim_sources) = app.state.wim_sources.lock()
|
if let Ok(wim_sources) = app.state.wim_sources.lock()
|
||||||
|
|
@ -885,7 +717,7 @@ fn build_right_items(app: &App) -> Action {
|
||||||
}])
|
}])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Mode::Confirm | Mode::PreClone | Mode::Clone | Mode::PostClone => {
|
Mode::Confirm => {
|
||||||
if let Some(index) = app.state.wim_image_index
|
if let Some(index) = app.state.wim_image_index
|
||||||
&& let Some(image) = wim_file.images.get(index)
|
&& let Some(image) = wim_file.images.get(index)
|
||||||
{
|
{
|
||||||
|
|
@ -897,7 +729,7 @@ fn build_right_items(app: &App) -> Action {
|
||||||
DVLine::blank(),
|
DVLine::blank(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if !wim_file.is_backup
|
if wim_file.is_setup
|
||||||
&& let Some(username) = &app.state.username
|
&& let Some(username) = &app.state.username
|
||||||
{
|
{
|
||||||
label_dv_lines.append(&mut vec![DVLine {
|
label_dv_lines.append(&mut vec![DVLine {
|
||||||
|
|
@ -1010,35 +842,3 @@ fn get_chunks(r: Rect) -> Vec<Rect> {
|
||||||
// Done
|
// Done
|
||||||
chunks
|
chunks
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_program_files_path(action_tx: &mpsc::UnboundedSender<Action>) -> String {
|
|
||||||
let mut program_files_path = String::from(".");
|
|
||||||
if cfg!(windows) {
|
|
||||||
if let Ok(path) = env::var("PROGRAMFILES") {
|
|
||||||
program_files_path = path;
|
|
||||||
} else {
|
|
||||||
action_tx
|
|
||||||
.send(Action::Error(String::from(
|
|
||||||
"ERROR\n\n\nFailed to find PROGRAMFILES",
|
|
||||||
)))
|
|
||||||
.expect("Failed to find PROGRAMFILES and then failed to send action");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
program_files_path
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_system32_path(action_tx: &mpsc::UnboundedSender<Action>) -> String {
|
|
||||||
let mut system32_path = String::from(".");
|
|
||||||
if cfg!(windows) {
|
|
||||||
if let Ok(path) = env::var("SYSTEMROOT") {
|
|
||||||
system32_path = format!("{path}/System32");
|
|
||||||
} else {
|
|
||||||
action_tx
|
|
||||||
.send(Action::Error(String::from(
|
|
||||||
"ERROR\n\n\nFailed to find SYSTEMROOT",
|
|
||||||
)))
|
|
||||||
.expect("Failed to find SYSTEMROOT and then failed to send action");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
system32_path
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_all(&mut self) {
|
pub fn reset_all(&mut self) {
|
||||||
|
self.disk_index_dest = None;
|
||||||
self.wim_file_index = None;
|
self.wim_file_index = None;
|
||||||
self.wim_image_index = None;
|
self.wim_image_index = None;
|
||||||
if let Ok(mut sources) = self.wim_sources.lock() {
|
if let Ok(mut sources) = self.wim_sources.lock() {
|
||||||
|
|
@ -153,13 +154,13 @@ pub fn scan_local_drives(
|
||||||
|
|
||||||
// Scan drives
|
// Scan drives
|
||||||
to_check.iter().for_each(|scan_path| {
|
to_check.iter().for_each(|scan_path| {
|
||||||
let is_backup = !scan_path.ends_with("\\Images");
|
let is_setup = scan_path.ends_with("\\Images");
|
||||||
if let Ok(read_dir) = read_dir(scan_path) {
|
if let Ok(read_dir) = read_dir(scan_path) {
|
||||||
read_dir.for_each(|item| {
|
read_dir.for_each(|item| {
|
||||||
if let Ok(item) = item
|
if let Ok(item) = item
|
||||||
&& item.file_name().to_string_lossy().ends_with(".wim")
|
&& item.file_name().to_string_lossy().ends_with(".wim")
|
||||||
&& let Some(path_str) = item.path().to_str()
|
&& let Some(path_str) = item.path().to_str()
|
||||||
&& let Ok(new_source) = parse_wim_file(path_str, is_backup)
|
&& let Ok(new_source) = parse_wim_file(path_str, is_setup)
|
||||||
{
|
{
|
||||||
wim_files.push(new_source);
|
wim_files.push(new_source);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ static WIN_BUILDS: LazyLock<HashMap<&str, &str>> = LazyLock::new(|| {
|
||||||
pub struct WimFile {
|
pub struct WimFile {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub images: Vec<WimImage>,
|
pub images: Vec<WimImage>,
|
||||||
pub is_backup: bool,
|
pub is_setup: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WimFile {
|
impl WimFile {
|
||||||
|
|
@ -237,7 +237,7 @@ fn get_wim_xml(wim_file: &str) -> std::io::Result<File> {
|
||||||
Ok(file)
|
Ok(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_wim_file(wim_file: &str, is_backup: bool) -> std::io::Result<WimFile> {
|
pub fn parse_wim_file(wim_file: &str, is_setup: bool) -> std::io::Result<WimFile> {
|
||||||
let mut wim_images: Vec<WimImage> = Vec::new();
|
let mut wim_images: Vec<WimImage> = Vec::new();
|
||||||
if !Path::new(wim_file).exists() {
|
if !Path::new(wim_file).exists() {
|
||||||
return Err(std::io::Error::new(
|
return Err(std::io::Error::new(
|
||||||
|
|
@ -316,7 +316,7 @@ pub fn parse_wim_file(wim_file: &str, is_backup: bool) -> std::io::Result<WimFil
|
||||||
let wim_file = WimFile {
|
let wim_file = WimFile {
|
||||||
path: wim_file.to_string(),
|
path: wim_file.to_string(),
|
||||||
images: wim_images,
|
images: wim_images,
|
||||||
is_backup,
|
is_setup,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(wim_file)
|
Ok(wim_file)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue