winbrew_app\operations\doctor\scan/
mod.rs1use crate::models::domains::installed::InstalledPackage;
8use crate::models::domains::reporting::{DiagnosisResult, DiagnosisSeverity, RecoveryFinding};
9
10mod journal;
11mod msi;
12mod orphan;
13mod package;
14
15pub(super) use msi::{MsiInventoryScan, scan_msi_inventory};
16pub(super) use package::{PackageInstallScan, installed_packages, scan_packages};
17
18#[derive(Debug, Default)]
19pub(super) struct ScanResult {
20 pub(super) diagnostics: Vec<DiagnosisResult>,
21 pub(super) recovery_findings: Vec<RecoveryFinding>,
22}
23
24impl ScanResult {
25 fn push(&mut self, diagnosis: DiagnosisResult, target_path: Option<&std::path::Path>) {
26 if let Some(finding) = RecoveryFinding::from_diagnosis(&diagnosis) {
27 let finding = match target_path {
28 Some(target_path) => {
29 finding.with_target_path(target_path.to_string_lossy().into_owned())
30 }
31 None => finding,
32 };
33 self.recovery_findings.push(finding);
34 }
35
36 self.diagnostics.push(diagnosis);
37 }
38
39 fn push_orphan(&mut self, package_name: &str, path: &std::path::Path) {
40 let diagnosis = DiagnosisResult {
41 error_code: "orphan_install_directory".to_string(),
42 description: format!(
43 "{}: orphan install directory ({})",
44 package_name,
45 path.to_string_lossy()
46 ),
47 severity: DiagnosisSeverity::Warning,
48 };
49
50 self.push(diagnosis, Some(path));
51 }
52}
53
54pub(super) type PackageJournalScan = ScanResult;
55pub(super) type OrphanInstallScan = ScanResult;
56
57pub(super) fn scan_package_journals(
58 paths: &crate::core::paths::ResolvedPaths,
59 packages: &[InstalledPackage],
60) -> PackageJournalScan {
61 journal::scan_package_journals(paths, packages)
62}
63
64pub(super) fn scan_orphaned_install_dirs(
65 packages_root: &std::path::Path,
66 packages: &[InstalledPackage],
67) -> OrphanInstallScan {
68 orphan::scan_orphaned_install_dirs(packages_root, packages)
69}
70
71pub(super) fn sort_diagnoses(diagnoses: &mut [DiagnosisResult]) {
73 diagnoses.sort_unstable_by(|left, right| {
74 left.error_code
75 .cmp(&right.error_code)
76 .then_with(|| left.description.cmp(&right.description))
77 });
78}
79
80pub(super) fn sort_recovery_findings(findings: &mut [RecoveryFinding]) {
81 findings.sort_unstable_by(|left, right| {
82 left.severity
83 .cmp(&right.severity)
84 .then_with(|| left.error_code.cmp(&right.error_code))
85 .then_with(|| left.target_path.cmp(&right.target_path))
86 .then_with(|| left.description.cmp(&right.description))
87 });
88}