Compare commits
3 commits
4fca7d6696
...
9f0ecb9baf
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f0ecb9baf | |||
| 5ba30e626f | |||
| ee7147a187 |
2 changed files with 208 additions and 14 deletions
|
|
@ -14,7 +14,7 @@
|
|||
// along with Deja-Vu. If not, see <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
use core::{
|
||||
action::Action,
|
||||
action::{Action, DiagResult},
|
||||
components::{
|
||||
Component,
|
||||
footer::Footer,
|
||||
|
|
@ -54,7 +54,10 @@ use ratatui::{
|
|||
use tokio::sync::mpsc;
|
||||
use tracing::{debug, info};
|
||||
|
||||
use crate::diags::{DiagGroup, Type as DiagType, get_diag_type, parse_bitlocker, parse_chkdsk};
|
||||
use crate::diags::{
|
||||
DiagGroup, Type as DiagType, get_diag_type, parse_bcd, parse_bitlocker, parse_chkdsk,
|
||||
parse_dism, parse_system_files,
|
||||
};
|
||||
|
||||
pub struct App {
|
||||
// TUI
|
||||
|
|
@ -450,13 +453,32 @@ impl App {
|
|||
parse_bitlocker(current_group, task_result.clone());
|
||||
}
|
||||
}
|
||||
DiagType::BootConfigData => {
|
||||
if let Some(task_result) = &task.result {
|
||||
parse_bcd(current_group, task_result.clone());
|
||||
}
|
||||
}
|
||||
DiagType::CheckDisk => {
|
||||
if let Some(task_result) = &task.result {
|
||||
parse_chkdsk(current_group, task_result.clone());
|
||||
}
|
||||
}
|
||||
DiagType::ComponentStore => {
|
||||
if let Some(task_result) = &task.result {
|
||||
parse_dism(current_group, task_result.clone());
|
||||
}
|
||||
}
|
||||
DiagType::SystemFiles => {
|
||||
if let Some(task_result) = &task.result {
|
||||
parse_system_files(current_group, task_result.clone());
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
self.action_tx.send(Action::DiagLineUpdate {
|
||||
result: current_group.get_pass_fail_warn(),
|
||||
text: current_group.result.clone(),
|
||||
})?;
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
|
|
@ -576,7 +598,11 @@ impl App {
|
|||
DiagType::ComponentStore.to_string().as_str(),
|
||||
vec![TaskType::CommandWait(
|
||||
PathBuf::from(format!("{}\\dism.exe", &self.system32)),
|
||||
vec![format!("{letter_os}:")],
|
||||
vec![
|
||||
format!("/Image:{letter_os}:"),
|
||||
String::from("/Cleanup-Image"),
|
||||
String::from("/ScanHealth"),
|
||||
],
|
||||
)],
|
||||
);
|
||||
|
||||
|
|
@ -833,7 +859,7 @@ fn build_left_items(app: &App) -> Action {
|
|||
.iter()
|
||||
.map(|group| {
|
||||
let label = group.diag_type.to_string();
|
||||
let status = if group.passed {
|
||||
let status = if group.get_pass_fail_warn() == DiagResult::Pass {
|
||||
"" // Leave blank if OK
|
||||
} else {
|
||||
" -- Issue(s) detected"
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// 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 core::{line::DVLine, tasks::TaskResult};
|
||||
use core::{action::DiagResult, line::DVLine, tasks::TaskResult};
|
||||
use std::{fmt, sync::OnceLock, thread::sleep, time::Duration};
|
||||
|
||||
use ratatui::style::Color;
|
||||
|
|
@ -93,7 +93,7 @@ pub struct Log {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct DiagGroup {
|
||||
pub diag_type: Type,
|
||||
pub passed: bool,
|
||||
pub passed: Vec<bool>,
|
||||
pub logs: Vec<Log>,
|
||||
pub result: String,
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ impl DiagGroup {
|
|||
pub fn new(diag_type: Type) -> Self {
|
||||
DiagGroup {
|
||||
diag_type,
|
||||
passed: true,
|
||||
passed: Vec::new(),
|
||||
logs: Vec::new(),
|
||||
result: String::new(),
|
||||
}
|
||||
|
|
@ -124,6 +124,18 @@ impl DiagGroup {
|
|||
.for_each(|log| summaries.extend(log.summary.clone().into_iter()));
|
||||
summaries
|
||||
}
|
||||
|
||||
pub fn get_pass_fail_warn(&self) -> DiagResult {
|
||||
let all_passed = self.passed.iter().fold(true, |acc, result| acc && *result);
|
||||
let all_failed = self.passed.iter().fold(true, |acc, result| acc && !*result);
|
||||
if all_passed {
|
||||
DiagResult::Pass
|
||||
} else if all_failed {
|
||||
DiagResult::Fail
|
||||
} else {
|
||||
DiagResult::Warn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_diag_type(label: &str) -> Type {
|
||||
|
|
@ -142,6 +154,58 @@ pub fn get_diag_type(label: &str) -> Type {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_bcd(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
||||
if !cfg!(windows) {
|
||||
sleep(Duration::from_millis(500));
|
||||
return ();
|
||||
}
|
||||
match task_result {
|
||||
TaskResult::Error(err) => {
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("BCD"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("BCD: "), String::from("Error")],
|
||||
line_colors: vec![Color::Reset, Color::Red],
|
||||
}],
|
||||
raw: err,
|
||||
});
|
||||
}
|
||||
TaskResult::Output(stdout, stderr, passed) => {
|
||||
let output_text = if stderr.is_empty() {
|
||||
stdout.clone()
|
||||
} else {
|
||||
format!("{stdout}\n\n-------\n\n{stderr}")
|
||||
};
|
||||
|
||||
if passed {
|
||||
diag_group.passed.push(true);
|
||||
diag_group.result = String::from("OK");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("BCD"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("BCD: "), String::from("OK")],
|
||||
line_colors: vec![Color::Reset, Color::Green],
|
||||
}],
|
||||
raw: output_text,
|
||||
});
|
||||
} else {
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Unknown");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("BCD"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("BCD: "), String::from("Unknown")],
|
||||
line_colors: vec![Color::Reset, Color::Yellow],
|
||||
}],
|
||||
raw: output_text,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_bitlocker(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
||||
if !cfg!(windows) {
|
||||
sleep(Duration::from_millis(500));
|
||||
|
|
@ -151,7 +215,7 @@ pub fn parse_bitlocker(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
let re_bitlocker_off = REGEXES.bitlocker_off();
|
||||
match task_result {
|
||||
TaskResult::Error(err) => {
|
||||
diag_group.passed = false;
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("Bitlocker"),
|
||||
|
|
@ -172,7 +236,7 @@ pub fn parse_bitlocker(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
let set_result_text = !output_text.contains("All Key Protectors");
|
||||
|
||||
if re_bitlocker_off.is_match(&output_text) {
|
||||
diag_group.passed &= true;
|
||||
diag_group.passed.push(true);
|
||||
result = String::from("OK");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("Bitlocker"),
|
||||
|
|
@ -183,7 +247,7 @@ pub fn parse_bitlocker(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
raw: output_text,
|
||||
});
|
||||
} else if re_bitlocker_locked.is_match(&output_text) {
|
||||
diag_group.passed = false;
|
||||
diag_group.passed.push(false);
|
||||
result = String::from("Locked");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("Bitlocker"),
|
||||
|
|
@ -194,7 +258,7 @@ pub fn parse_bitlocker(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
raw: output_text,
|
||||
});
|
||||
} else {
|
||||
diag_group.passed &= true;
|
||||
diag_group.passed.push(true);
|
||||
result = String::from("Unknown");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("Bitlocker"),
|
||||
|
|
@ -216,7 +280,7 @@ pub fn parse_chkdsk(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
}
|
||||
match task_result {
|
||||
TaskResult::Error(err) => {
|
||||
diag_group.passed = false;
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("CHKDSK"),
|
||||
|
|
@ -241,7 +305,7 @@ pub fn parse_chkdsk(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
|
||||
if parsed_output.contains("Windows has scanned the file system and found no problems.")
|
||||
{
|
||||
diag_group.passed &= true;
|
||||
diag_group.passed.push(true);
|
||||
diag_group.result = String::from("OK");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("CHKDSK"),
|
||||
|
|
@ -252,7 +316,7 @@ pub fn parse_chkdsk(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
raw: parsed_output,
|
||||
});
|
||||
} else {
|
||||
diag_group.passed = false;
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("CHKDSK"),
|
||||
|
|
@ -267,6 +331,110 @@ pub fn parse_chkdsk(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse_dism(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
||||
if !cfg!(windows) {
|
||||
sleep(Duration::from_millis(500));
|
||||
return ();
|
||||
}
|
||||
match task_result {
|
||||
TaskResult::Error(err) => {
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("DISM"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("DISM: "), String::from("Error")],
|
||||
line_colors: vec![Color::Reset, Color::Red],
|
||||
}],
|
||||
raw: err,
|
||||
});
|
||||
}
|
||||
TaskResult::Output(stdout, stderr, _) => {
|
||||
let output_text = if stderr.is_empty() {
|
||||
stdout.clone()
|
||||
} else {
|
||||
format!("{stdout}\n\n-------\n\n{stderr}")
|
||||
};
|
||||
|
||||
if output_text.contains("no component store corruption detected") {
|
||||
diag_group.passed.push(true);
|
||||
diag_group.result = String::from("OK");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("DISM"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("DISM: "), String::from("OK")],
|
||||
line_colors: vec![Color::Reset, Color::Green],
|
||||
}],
|
||||
raw: output_text,
|
||||
});
|
||||
} else {
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Unknown");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("DISM"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("DISM: "), String::from("Unknown")],
|
||||
line_colors: vec![Color::Reset, Color::Yellow],
|
||||
}],
|
||||
raw: output_text,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_system_files(diag_group: &mut DiagGroup, task_result: TaskResult) {
|
||||
if !cfg!(windows) {
|
||||
sleep(Duration::from_millis(500));
|
||||
return ();
|
||||
}
|
||||
match task_result {
|
||||
TaskResult::Error(err) => {
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("System Files"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("System Files: "), String::from("Error")],
|
||||
line_colors: vec![Color::Reset, Color::Red],
|
||||
}],
|
||||
raw: err,
|
||||
});
|
||||
}
|
||||
TaskResult::Output(stdout, stderr, passed) => {
|
||||
let output_text = if stderr.is_empty() {
|
||||
stdout.clone()
|
||||
} else {
|
||||
format!("{stdout}\n\n{stderr}")
|
||||
};
|
||||
|
||||
if passed {
|
||||
diag_group.passed.push(true);
|
||||
diag_group.result = String::from("OK");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("System Files"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("System Files: "), String::from("OK")],
|
||||
line_colors: vec![Color::Reset, Color::Green],
|
||||
}],
|
||||
raw: output_text,
|
||||
});
|
||||
} else {
|
||||
diag_group.passed.push(false);
|
||||
diag_group.result = String::from("Error");
|
||||
diag_group.logs.push(Log {
|
||||
label: String::from("System Files"),
|
||||
summary: vec![DVLine {
|
||||
line_parts: vec![String::from("System Files: "), String::from("Error")],
|
||||
line_colors: vec![Color::Reset, Color::Red],
|
||||
}],
|
||||
raw: output_text,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_carriage_returns(text: &str) -> String {
|
||||
let re_carriage_returns = REGEXES.carriage_returns();
|
||||
let parsed_lines: Vec<String> = text
|
||||
|
|
|
|||
Loading…
Reference in a new issue