Major refactor around task groups
This commit is contained in:
parent
081fd22de1
commit
2296b8f274
8 changed files with 138 additions and 254 deletions
|
|
@ -39,7 +39,6 @@ use core::{
|
|||
tui::{Event, Tui},
|
||||
};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
env,
|
||||
iter::zip,
|
||||
path::PathBuf,
|
||||
|
|
@ -54,7 +53,7 @@ use ratatui::{
|
|||
style::Color,
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
use tracing::{debug, info, warn};
|
||||
use tracing::{debug, info};
|
||||
|
||||
pub struct App {
|
||||
// TUI
|
||||
|
|
@ -76,7 +75,6 @@ pub struct App {
|
|||
selections: Vec<Option<usize>>,
|
||||
system32: String,
|
||||
tasks: Tasks,
|
||||
task_groups: VecDeque<Option<String>>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
|
@ -120,7 +118,6 @@ impl App {
|
|||
system32: String::new(),
|
||||
selections: vec![None, None],
|
||||
tasks,
|
||||
task_groups: VecDeque::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -401,20 +398,12 @@ impl App {
|
|||
self.action_tx.send(Action::Select(None, None))?;
|
||||
}
|
||||
Action::TaskGroupStart(ref title) => {
|
||||
// TODO: Verify this isn't broken and/or unused
|
||||
if self.cur_mode == Mode::BootScan {
|
||||
info!("TaskGroup: {:?}", self.task_groups.front());
|
||||
if self.task_groups.front().is_some() {
|
||||
if self.task_groups.front().unwrap().is_some() {
|
||||
// None here means that we're in the middle of a group of tasks
|
||||
// i.e. don't start a new diag line
|
||||
self.action_tx.send(Action::DiagStartLine {
|
||||
text: title.clone(),
|
||||
})?;
|
||||
}
|
||||
}
|
||||
if !self.diag_groups.contains(&title) {
|
||||
self.diag_groups.update(title.to_owned(), None, None);
|
||||
}
|
||||
self.action_tx.send(Action::DiagLineStart {
|
||||
text: title.clone(),
|
||||
})?;
|
||||
self.diag_groups.start(title.to_owned());
|
||||
}
|
||||
}
|
||||
Action::TasksComplete => {
|
||||
|
|
@ -443,70 +432,22 @@ impl App {
|
|||
|
||||
fn handle_task(&mut self, task: &Task) -> Result<()> {
|
||||
info!("Handling Task: {task:?}");
|
||||
let title: Option<String>;
|
||||
match self.cur_mode {
|
||||
Mode::BootScan => {
|
||||
let task_group = self.task_groups.pop_front();
|
||||
match &task.task_type {
|
||||
TaskType::CommandWait(cmd_path, _cmd_args) => {
|
||||
let mut cmd_name = "";
|
||||
if let Some(path) = cmd_path.file_name() {
|
||||
if let Some(cmd_str) = path.to_str() {
|
||||
cmd_name = cmd_str;
|
||||
}
|
||||
};
|
||||
let diag_type = diags::get_type(cmd_name);
|
||||
match diag_type {
|
||||
diags::Type::Bitlocker
|
||||
| diags::Type::BootConfigData
|
||||
| diags::Type::Registry
|
||||
| diags::Type::System => {
|
||||
title = Some(format!("{diag_type}"));
|
||||
}
|
||||
diags::Type::FileSystem => {
|
||||
title = None;
|
||||
if let Some(result) = &task.result {
|
||||
let passed: bool;
|
||||
let info: String;
|
||||
match result {
|
||||
TaskResult::Error(msg) => {
|
||||
passed = false;
|
||||
info = msg.to_owned();
|
||||
}
|
||||
TaskResult::Output(stdout, _stderr, success) => {
|
||||
passed = *success;
|
||||
info = parse_chkdsk(stdout);
|
||||
}
|
||||
}
|
||||
self.diag_groups.update(
|
||||
String::from("Filesystem"),
|
||||
Some(passed),
|
||||
Some(info.to_owned()),
|
||||
);
|
||||
}
|
||||
}
|
||||
diags::Type::Unknown => {
|
||||
title = None;
|
||||
warn!("Unrecognized command: {:?}", &cmd_path);
|
||||
}
|
||||
};
|
||||
}
|
||||
TaskType::TestPaths(_) => {
|
||||
title = Some(format!("{}", diags::Type::FileSystem));
|
||||
}
|
||||
_ => title = None,
|
||||
}
|
||||
if let Some(title_str) = title {
|
||||
if let Some(result) = &task.result {
|
||||
let passed: bool;
|
||||
let info: String;
|
||||
match result {
|
||||
TaskResult::Error(msg) => {
|
||||
passed = false;
|
||||
info = msg.to_owned();
|
||||
}
|
||||
TaskResult::Output(stdout, stderr, success) => {
|
||||
passed = *success;
|
||||
if let Some(result) = &task.result {
|
||||
let title = self.diag_groups.current_group();
|
||||
let passed: bool;
|
||||
let info: String;
|
||||
match result {
|
||||
TaskResult::Error(msg) => {
|
||||
passed = false;
|
||||
info = msg.to_owned();
|
||||
}
|
||||
TaskResult::Output(stdout, stderr, success) => {
|
||||
passed = *success;
|
||||
if title == "Filesystem" {
|
||||
info = parse_chkdsk(stdout);
|
||||
} else {
|
||||
let div = if !(stdout.is_empty() || stderr.is_empty()) {
|
||||
"\n\n-----------\n\n"
|
||||
} else {
|
||||
|
|
@ -515,37 +456,19 @@ impl App {
|
|||
info = format!("{stdout}{div}{stderr}");
|
||||
}
|
||||
}
|
||||
self.diag_groups
|
||||
.update(title_str, Some(passed), Some(info.to_owned()));
|
||||
if let Some(group) = task_group {
|
||||
if let Some(wat) = group {
|
||||
info!("WAT? // {wat:?}");
|
||||
if passed {
|
||||
self.action_tx.send(Action::DiagEndLine {
|
||||
result: DiagResult::Pass,
|
||||
text: String::from("Pass?"),
|
||||
})?;
|
||||
} else {
|
||||
self.action_tx.send(Action::DiagEndLine {
|
||||
result: DiagResult::Fail,
|
||||
text: String::from("Fail?"),
|
||||
})?;
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If title was set but there wasn't a result
|
||||
self.action_tx.send(Action::DiagEndLine {
|
||||
result: DiagResult::Warn,
|
||||
text: String::from("Yellow no result?"),
|
||||
})?;
|
||||
}
|
||||
} else {
|
||||
// title was not set
|
||||
self.action_tx.send(Action::DiagEndLine {
|
||||
result: DiagResult::Warn,
|
||||
text: String::from("Yellow no title?"),
|
||||
})?;
|
||||
self.diag_groups.update(title, passed, info);
|
||||
if passed {
|
||||
self.action_tx.send(Action::DiagLineUpdate {
|
||||
result: DiagResult::Pass,
|
||||
text: String::from("Pass?"),
|
||||
})?;
|
||||
} else {
|
||||
self.action_tx.send(Action::DiagLineUpdate {
|
||||
result: DiagResult::Fail,
|
||||
text: String::from("Fail?"),
|
||||
})?;
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
@ -577,6 +500,11 @@ impl App {
|
|||
}
|
||||
}
|
||||
}
|
||||
TaskType::GroupEnd { ref label } => {
|
||||
self.action_tx.send(Action::DiagLineEnd {
|
||||
text: label.clone(),
|
||||
})?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -626,7 +554,6 @@ impl App {
|
|||
],
|
||||
)],
|
||||
);
|
||||
self.task_groups.push_back(Some(String::from("Boot Files")));
|
||||
}
|
||||
|
||||
// Bitlocker
|
||||
|
|
@ -647,7 +574,6 @@ impl App {
|
|||
),
|
||||
],
|
||||
);
|
||||
self.task_groups.push_back(Some(String::from("Bitlocker")));
|
||||
|
||||
// Filesystem Health
|
||||
let paths: Vec<PathBuf> = [
|
||||
|
|
@ -671,7 +597,6 @@ impl App {
|
|||
TaskType::TestPaths(paths),
|
||||
],
|
||||
);
|
||||
self.task_groups.push_back(Some(String::from("Filesystem")));
|
||||
|
||||
// DISM Health
|
||||
self.tasks.add_group(
|
||||
|
|
@ -681,8 +606,6 @@ impl App {
|
|||
vec![format!("{letter_os}:")],
|
||||
)],
|
||||
);
|
||||
self.task_groups
|
||||
.push_back(Some(String::from("System Files")));
|
||||
|
||||
// Registry
|
||||
self.tasks.add_group(
|
||||
|
|
@ -726,7 +649,6 @@ impl App {
|
|||
),
|
||||
],
|
||||
);
|
||||
self.task_groups.push_back(Some(String::from("Registry")));
|
||||
self.tasks.add(TaskType::Sleep); // NOTE: DELETEME
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct ProgressLine {
|
|||
name: String,
|
||||
text: String,
|
||||
result: DiagResult,
|
||||
running: bool,
|
||||
}
|
||||
|
||||
impl ProgressLine {
|
||||
|
|
@ -70,17 +71,18 @@ impl Progress {
|
|||
impl Component for Progress {
|
||||
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
||||
match action {
|
||||
Action::DiagStartLine { text } => {
|
||||
info!("Caught Action::DiagStartLine");
|
||||
Action::DiagLineStart { text } => {
|
||||
info!("Caught Action::DiagLineStart {{ \"{}\" }}", &text);
|
||||
self.lines.push(ProgressLine {
|
||||
name: text,
|
||||
text: String::new(),
|
||||
text: String::from("OK"),
|
||||
result: DiagResult::Pass,
|
||||
running: true,
|
||||
});
|
||||
}
|
||||
Action::DiagEndLine { result, text } => {
|
||||
Action::DiagLineUpdate { result, text } => {
|
||||
info!(
|
||||
"Caught Action::DiagEndLine {{ {}, \"{}\" }}",
|
||||
"Caught Action::DiagLineUpdate {{ {}, \"{}\" }}",
|
||||
&result, &text
|
||||
);
|
||||
if let Some(line) = self.lines.last_mut() {
|
||||
|
|
@ -88,6 +90,12 @@ impl Component for Progress {
|
|||
line.text = text;
|
||||
}
|
||||
}
|
||||
Action::DiagLineEnd { text } => {
|
||||
info!("Caught Action::DiagLineEnd {{ \"{}\" }}", &text);
|
||||
if let Some(line) = self.lines.last_mut() {
|
||||
line.running = false;
|
||||
}
|
||||
}
|
||||
Action::SetMode(mode) => self.mode = mode,
|
||||
_ => {}
|
||||
};
|
||||
|
|
@ -111,7 +119,7 @@ impl Component for Progress {
|
|||
DiagResult::Fail => Color::Red,
|
||||
DiagResult::Warn => Color::Yellow,
|
||||
};
|
||||
let text = if line.text.is_empty() {
|
||||
let text = if line.running || line.text.is_empty() {
|
||||
String::from("...")
|
||||
} else {
|
||||
line.text.clone()
|
||||
|
|
|
|||
|
|
@ -13,29 +13,9 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with Deja-Vu. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{collections::HashMap, fmt};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub enum Type {
|
||||
Bitlocker,
|
||||
BootConfigData,
|
||||
FileSystem,
|
||||
Registry,
|
||||
System,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Type::Bitlocker => write!(f, "Bitlocker"),
|
||||
Type::BootConfigData => write!(f, "Boot Files"),
|
||||
Type::FileSystem => write!(f, "Filesystem"),
|
||||
Type::Registry => write!(f, "Registry"),
|
||||
Type::System => write!(f, "System Files"),
|
||||
Type::Unknown => write!(f, "Unknown Type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
use tracing::warn;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Groups {
|
||||
|
|
@ -51,8 +31,11 @@ impl Groups {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn contains(&self, name: &str) -> bool {
|
||||
self.items.contains_key(name)
|
||||
pub fn current_group(&self) -> String {
|
||||
match self.order.last() {
|
||||
Some(label) => label.clone(),
|
||||
None => String::from("No current group"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Vec<&Line> {
|
||||
|
|
@ -65,24 +48,24 @@ impl Groups {
|
|||
lines
|
||||
}
|
||||
|
||||
pub fn update(&mut self, title: String, passed: Option<bool>, info: Option<String>) {
|
||||
pub fn start(&mut self, title: String) {
|
||||
self.order.push(title.clone());
|
||||
self.items.insert(
|
||||
title.clone(),
|
||||
Line {
|
||||
title,
|
||||
passed: true,
|
||||
info: Vec::new(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn update(&mut self, title: String, passed: bool, info: String) {
|
||||
if let Some(line) = self.items.get_mut(&title) {
|
||||
line.update(passed, info);
|
||||
} else {
|
||||
let info_list = if info.is_some() {
|
||||
vec![info.unwrap()]
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
self.order.push(title.clone());
|
||||
self.items.insert(
|
||||
title.clone(),
|
||||
Line {
|
||||
title,
|
||||
passed: passed.unwrap_or(true),
|
||||
info: info_list,
|
||||
},
|
||||
);
|
||||
warn!("WARNING/DELETEME - This shouldn't happen?!");
|
||||
self.start(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,34 +78,8 @@ pub struct Line {
|
|||
}
|
||||
|
||||
impl Line {
|
||||
pub fn update(&mut self, passed: Option<bool>, info: Option<String>) {
|
||||
if let Some(result) = passed {
|
||||
self.passed &= result; // We fail if any tests in this group fail
|
||||
}
|
||||
if let Some(info_str) = info {
|
||||
self.info.push(String::from(info_str));
|
||||
}
|
||||
pub fn update(&mut self, passed: bool, info: String) {
|
||||
self.passed &= passed; // We fail if any tests in this group fail
|
||||
self.info.push(info);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_type(cmd_name: &str) -> Type {
|
||||
if cmd_name.ends_with("exa") {
|
||||
return Type::BootConfigData;
|
||||
}
|
||||
if cmd_name.ends_with("bcdedit.exe") {
|
||||
return Type::BootConfigData;
|
||||
}
|
||||
if cmd_name.ends_with("dism.exe") {
|
||||
return Type::System;
|
||||
}
|
||||
if cmd_name.ends_with("reg.exe") {
|
||||
return Type::Registry;
|
||||
}
|
||||
if cmd_name.ends_with("chkdsk.exe") {
|
||||
return Type::FileSystem;
|
||||
}
|
||||
if cmd_name.ends_with("manage-bde.exe") {
|
||||
return Type::Bitlocker;
|
||||
}
|
||||
Type::Unknown
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ pub enum DiagResult {
|
|||
pub enum Action {
|
||||
// App (Boot-Diags)
|
||||
BootScan,
|
||||
DiagStartLine { text: String },
|
||||
DiagEndLine { result: DiagResult, text: String },
|
||||
DiagLineStart { text: String },
|
||||
DiagLineUpdate { result: DiagResult, text: String },
|
||||
DiagLineEnd { text: String },
|
||||
// App (Clone)
|
||||
Highlight(usize),
|
||||
InstallDriver,
|
||||
|
|
@ -44,7 +45,6 @@ pub enum Action {
|
|||
Select(Option<usize>, Option<usize>), // indicies for (source, dest) etc
|
||||
SelectRight(Option<usize>, Option<usize>), // indicies for right info pane
|
||||
TaskGroupStart(String),
|
||||
TaskGroupEnd,
|
||||
TasksComplete,
|
||||
UpdateDiskList(Vec<Disk>),
|
||||
UpdateFooter(String),
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ impl FpsCounter {
|
|||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
mode: String::from(""),
|
||||
mode: String::new(),
|
||||
last_tick_update: Instant::now(),
|
||||
tick_count: 0,
|
||||
ticks_per_second: 0.0,
|
||||
|
|
@ -92,7 +92,7 @@ impl Component for FpsCounter {
|
|||
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
||||
match action {
|
||||
Action::SetMode(mode) => {
|
||||
self.mode = format!("{:?}", mode);
|
||||
self.mode = format!("{mode:?}");
|
||||
}
|
||||
Action::Render => self.render_tick()?,
|
||||
Action::Tick => self.app_tick()?,
|
||||
|
|
|
|||
|
|
@ -166,7 +166,6 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
|||
letter: String::from("C"),
|
||||
part_type: String::from("7"),
|
||||
size: 104_857_600,
|
||||
..Default::default()
|
||||
},
|
||||
Partition {
|
||||
id: 2,
|
||||
|
|
@ -181,7 +180,6 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
|||
letter: String::from("D"),
|
||||
part_type: String::from("7"),
|
||||
size: 267_701_452_800,
|
||||
..Default::default()
|
||||
},
|
||||
Partition {
|
||||
id: 6,
|
||||
|
|
@ -190,7 +188,6 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
|||
letter: String::from("E"),
|
||||
part_type: String::from("7"),
|
||||
size: 524_288_000,
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
serial: "MDZ1243".to_string(),
|
||||
|
|
@ -209,7 +206,6 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
|||
letter: String::from("G"),
|
||||
part_type: String::from("7"),
|
||||
size: 249_998_951_424,
|
||||
..Default::default()
|
||||
}],
|
||||
serial: "000010000".to_string(),
|
||||
size: 250_000_000_000,
|
||||
|
|
@ -261,7 +257,6 @@ pub fn get_fake_disks() -> Vec<Disk> {
|
|||
letter: String::from("I"),
|
||||
part_type: String::from("EFI"),
|
||||
size: 209_715_200,
|
||||
..Default::default()
|
||||
},
|
||||
Partition {
|
||||
id: 2,
|
||||
|
|
|
|||
|
|
@ -33,57 +33,57 @@ use crate::system::disk::{
|
|||
static DEFAULT_MAX_DISKS: usize = 8;
|
||||
|
||||
struct RegexList {
|
||||
re_detail_all_disks: OnceLock<Regex>,
|
||||
re_detail_disk: OnceLock<Regex>,
|
||||
re_detail_partition: OnceLock<Regex>,
|
||||
re_disk_numbers: OnceLock<Regex>,
|
||||
re_list_disk: OnceLock<Regex>,
|
||||
re_list_partition: OnceLock<Regex>,
|
||||
re_list_volumes: OnceLock<Regex>,
|
||||
re_split_all_disks: OnceLock<Regex>,
|
||||
detail_all_disks: OnceLock<Regex>,
|
||||
detail_disk: OnceLock<Regex>,
|
||||
detail_partition: OnceLock<Regex>,
|
||||
disk_numbers: OnceLock<Regex>,
|
||||
list_disk: OnceLock<Regex>,
|
||||
list_partition: OnceLock<Regex>,
|
||||
list_volumes: OnceLock<Regex>,
|
||||
split_all_disks: OnceLock<Regex>,
|
||||
re_uuid: OnceLock<Regex>,
|
||||
}
|
||||
|
||||
impl RegexList {
|
||||
pub fn detail_all_disks(&self) -> &Regex {
|
||||
self.re_detail_all_disks.get_or_init(|| {
|
||||
self.detail_all_disks.get_or_init(|| {
|
||||
Regex::new(r"(?s)Disk (\d+) is now the selected disk.*?\r?\n\s*\r?\n(.*)").unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn detail_disk(&self) -> &Regex {
|
||||
self.re_detail_disk.get_or_init(|| {
|
||||
self.detail_disk.get_or_init(|| {
|
||||
Regex::new(r"(.*?)\r?\nDisk ID\s*:\s+(.*?)\r?\nType\s*:\s+(.*?)\r?\n").unwrap()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn detail_partition(&self) -> &Regex {
|
||||
self.re_detail_partition
|
||||
self.detail_partition
|
||||
.get_or_init(|| Regex::new(r"Partition (\d+)\r?\nType\s*: (\S+)(\r?\n.*){5}\s*(Volume.*\r?\n.*\r?\n|There is no volume)(.*)").unwrap())
|
||||
}
|
||||
|
||||
pub fn disk_numbers(&self) -> &Regex {
|
||||
self.re_disk_numbers
|
||||
self.disk_numbers
|
||||
.get_or_init(|| Regex::new(r"\s+Disk\s+(\d+).*\n.*\n.*\nDisk ID:").unwrap())
|
||||
}
|
||||
|
||||
pub fn list_disk(&self) -> &Regex {
|
||||
self.re_list_disk
|
||||
self.list_disk
|
||||
.get_or_init(|| Regex::new(r"Disk\s+(\d+)\s+(\w+)\s+(\d+\s+\w+B)").unwrap())
|
||||
}
|
||||
|
||||
pub fn list_partition(&self) -> &Regex {
|
||||
self.re_list_partition
|
||||
self.list_partition
|
||||
.get_or_init(|| Regex::new(r"Partition\s+(\d+)\s+\w+\s+(\d+\s+\w+B)").unwrap())
|
||||
}
|
||||
|
||||
pub fn split_all_disks(&self) -> &Regex {
|
||||
self.re_split_all_disks
|
||||
self.split_all_disks
|
||||
.get_or_init(|| Regex::new(r"Disk \d+ is now the selected disk").unwrap())
|
||||
}
|
||||
|
||||
pub fn list_volumes(&self) -> &Regex {
|
||||
self.re_list_volumes.get_or_init(|| {
|
||||
self.list_volumes.get_or_init(|| {
|
||||
// Volume ### Ltr Label Fs Type Size Status Info
|
||||
// ---------- --- ----------- ----- ---------- ------- --------- --------
|
||||
// * Volume 1 S ESP FAT32 Partition 100 MB Healthy Hidden
|
||||
|
|
@ -100,14 +100,14 @@ impl RegexList {
|
|||
}
|
||||
|
||||
static REGEXES: RegexList = RegexList {
|
||||
re_detail_all_disks: OnceLock::new(),
|
||||
re_detail_disk: OnceLock::new(),
|
||||
re_detail_partition: OnceLock::new(),
|
||||
re_disk_numbers: OnceLock::new(),
|
||||
re_list_disk: OnceLock::new(),
|
||||
re_list_partition: OnceLock::new(),
|
||||
re_list_volumes: OnceLock::new(),
|
||||
re_split_all_disks: OnceLock::new(),
|
||||
detail_all_disks: OnceLock::new(),
|
||||
detail_disk: OnceLock::new(),
|
||||
detail_partition: OnceLock::new(),
|
||||
disk_numbers: OnceLock::new(),
|
||||
list_disk: OnceLock::new(),
|
||||
list_partition: OnceLock::new(),
|
||||
list_volumes: OnceLock::new(),
|
||||
split_all_disks: OnceLock::new(),
|
||||
re_uuid: OnceLock::new(),
|
||||
};
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ pub fn get_partition_details(
|
|||
disk_details: Option<&str>,
|
||||
part_details: Option<&str>,
|
||||
) -> Vec<Partition> {
|
||||
let re_list_partitions = REGEXES.list_partition();
|
||||
let list_partitions = REGEXES.list_partition();
|
||||
let mut parts = Vec::new();
|
||||
|
||||
// List partition
|
||||
|
|
@ -163,7 +163,7 @@ pub fn get_partition_details(
|
|||
let script = format!("select disk {disk_id}\r\nlist partition");
|
||||
contents = run_script(&script);
|
||||
};
|
||||
for (_, [number, size]) in re_list_partitions
|
||||
for (_, [number, size]) in list_partitions
|
||||
.captures_iter(&contents)
|
||||
.map(|c| c.extract())
|
||||
{
|
||||
|
|
@ -274,8 +274,8 @@ pub fn build_get_disk_script(disk_nums: Option<Vec<&str>>) -> String {
|
|||
}
|
||||
|
||||
pub fn get_disks() -> Vec<Disk> {
|
||||
let re_detail_all_disks = REGEXES.detail_all_disks();
|
||||
let re_list_disk = REGEXES.list_disk();
|
||||
let detail_all_disks = REGEXES.detail_all_disks();
|
||||
let list_disk = REGEXES.list_disk();
|
||||
let mut contents: String;
|
||||
let mut output;
|
||||
let mut script: String;
|
||||
|
|
@ -317,7 +317,7 @@ pub fn get_disks() -> Vec<Disk> {
|
|||
// i.e. 0, 1, 3, 4
|
||||
// For instance, this can happen if a drive is disconnected after startup
|
||||
let mut disks_map: HashMap<&str, Disk> = HashMap::with_capacity(DEFAULT_MAX_DISKS);
|
||||
for (_, [number, _status, size]) in re_list_disk
|
||||
for (_, [number, _status, size]) in list_disk
|
||||
.captures_iter(dp_sections.remove(0)) // This is the "list disk" section
|
||||
.map(|c| c.extract())
|
||||
{
|
||||
|
|
@ -334,10 +334,7 @@ pub fn get_disks() -> Vec<Disk> {
|
|||
// Add Disk details
|
||||
let mut disks_raw: Vec<Disk> = Vec::with_capacity(DEFAULT_MAX_DISKS);
|
||||
for section in dp_sections {
|
||||
for (_, [id, details]) in re_detail_all_disks
|
||||
.captures_iter(section)
|
||||
.map(|c| c.extract())
|
||||
{
|
||||
for (_, [id, details]) in detail_all_disks.captures_iter(section).map(|c| c.extract()) {
|
||||
if let Some(disk) = disks_map.remove(id) {
|
||||
// We remove the disk from the HashMap because we're moving it to the Vec
|
||||
let mut disk = get_disk_details(disk.id, disk.size, Some(details));
|
||||
|
|
@ -357,19 +354,19 @@ pub fn parse_disk_numbers(contents: &str) -> Vec<&str> {
|
|||
//
|
||||
//Red Hat VirtIO SCSI Disk Device
|
||||
//Disk ID: {E9CE8DFA-46B2-43C1-99BB-850C661CEE6B}
|
||||
let re_disk_numbers = REGEXES.disk_numbers();
|
||||
let disk_numbers = REGEXES.disk_numbers();
|
||||
let mut disk_nums = Vec::new();
|
||||
for (_, [number]) in re_disk_numbers.captures_iter(contents).map(|c| c.extract()) {
|
||||
for (_, [number]) in disk_numbers.captures_iter(contents).map(|c| c.extract()) {
|
||||
disk_nums.push(number);
|
||||
}
|
||||
disk_nums
|
||||
}
|
||||
|
||||
pub fn parse_partition_details(parts: &mut [Partition], contents: &str) {
|
||||
let re_detail_partition = REGEXES.detail_partition();
|
||||
let re_list_volume = REGEXES.list_volumes();
|
||||
let detail_partition = REGEXES.detail_partition();
|
||||
let list_volume = REGEXES.list_volumes();
|
||||
|
||||
for (part_index, (_, [_part_id, part_type, _, _vol_header, vol_line])) in re_detail_partition
|
||||
for (part_index, (_, [_part_id, part_type, _, _vol_header, vol_line])) in detail_partition
|
||||
.captures_iter(contents)
|
||||
.map(|c| c.extract())
|
||||
.enumerate()
|
||||
|
|
@ -380,7 +377,7 @@ pub fn parse_partition_details(parts: &mut [Partition], contents: &str) {
|
|||
|
||||
// Volume info
|
||||
for (_, [_id, letter, label, fs_type]) in
|
||||
re_list_volume.captures_iter(vol_line).map(|c| c.extract())
|
||||
list_volume.captures_iter(vol_line).map(|c| c.extract())
|
||||
{
|
||||
part.label = String::from(label.trim());
|
||||
part.letter = String::from(letter.trim());
|
||||
|
|
@ -425,11 +422,11 @@ pub fn run_script(script: &str) -> String {
|
|||
|
||||
pub fn split_diskpart_disk_output(contents: &str) -> Vec<&str> {
|
||||
// NOTE: A simple split isn't helpful since we want to include the matching lines
|
||||
let re_split_all_disks = REGEXES.split_all_disks();
|
||||
let split_all_disks = REGEXES.split_all_disks();
|
||||
let mut sections = Vec::new();
|
||||
let mut starts: Vec<usize> = vec![0];
|
||||
let mut ends: Vec<usize> = Vec::new();
|
||||
let _: Vec<_> = re_split_all_disks
|
||||
let _: Vec<_> = split_all_disks
|
||||
.find_iter(contents)
|
||||
.map(|m| {
|
||||
ends.push(m.start() - 1);
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ pub enum TaskType {
|
|||
UpdateDestDisk(usize), // (disk_index)
|
||||
UpdateDiskList,
|
||||
GroupStart { label: String },
|
||||
GroupEnd,
|
||||
GroupEnd { label: String },
|
||||
}
|
||||
|
||||
impl fmt::Display for TaskType {
|
||||
|
|
@ -75,7 +75,7 @@ impl fmt::Display for TaskType {
|
|||
TaskType::UpdateDestDisk(_) => write!(f, "UpdateDestDisk"),
|
||||
TaskType::UpdateDiskList => write!(f, "UpdateDiskList"),
|
||||
TaskType::GroupStart { label } => write!(f, "GroupStart({})", &label),
|
||||
TaskType::GroupEnd => write!(f, "GroupEnd"),
|
||||
TaskType::GroupEnd { label } => write!(f, "GroupEnd({})", &label),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -136,10 +136,12 @@ impl Tasks {
|
|||
self.task_list.push_back(Task::new(TaskType::GroupStart {
|
||||
label: group_label.to_string(),
|
||||
}));
|
||||
group_tasks.into_iter().for_each(|task| {
|
||||
for task in group_tasks {
|
||||
self.task_list.push_back(Task::new(task));
|
||||
});
|
||||
self.task_list.push_back(Task::new(TaskType::GroupEnd));
|
||||
}
|
||||
self.task_list.push_back(Task::new(TaskType::GroupEnd {
|
||||
label: group_label.to_string(),
|
||||
}));
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
@ -249,9 +251,13 @@ impl Tasks {
|
|||
}));
|
||||
}
|
||||
TaskType::GroupStart { ref label } => {
|
||||
self.action_tx.send(Action::TaskGroupStart(label.clone()))?
|
||||
self.action_tx.send(Action::TaskGroupStart(label.clone()))?;
|
||||
}
|
||||
TaskType::GroupEnd { ref label } => {
|
||||
self.action_tx.send(Action::DiagLineEnd {
|
||||
text: label.clone(),
|
||||
})?;
|
||||
}
|
||||
TaskType::GroupEnd => self.action_tx.send(Action::TaskGroupEnd)?,
|
||||
}
|
||||
// Done
|
||||
self.cur_task.replace(task);
|
||||
|
|
@ -326,22 +332,21 @@ fn test_paths(
|
|||
) -> JoinHandle<()> {
|
||||
thread::spawn(move || {
|
||||
let mut missing_paths = Vec::new();
|
||||
let task_result: TaskResult;
|
||||
path_list.iter().for_each(|path| {
|
||||
for path in path_list {
|
||||
if !path.exists() {
|
||||
missing_paths.push(String::from(path.to_string_lossy()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if missing_paths.is_empty() {
|
||||
let task_result = if missing_paths.is_empty() {
|
||||
// No missing paths
|
||||
task_result = TaskResult::Output(String::from("OK"), String::new(), true);
|
||||
TaskResult::Output(String::from("OK"), String::new(), true)
|
||||
} else {
|
||||
task_result = TaskResult::Output(
|
||||
TaskResult::Output(
|
||||
String::from("Missing item(s)"),
|
||||
missing_paths.join(",\n"),
|
||||
false,
|
||||
);
|
||||
)
|
||||
};
|
||||
|
||||
let err_str = format!("Failed to send TaskResult: {:?}", &task_result);
|
||||
|
|
|
|||
Loading…
Reference in a new issue