diff --git a/win_installer/src/app.rs b/win_installer/src/app.rs index e3fbd9e..7d312f5 100644 --- a/win_installer/src/app.rs +++ b/win_installer/src/app.rs @@ -45,7 +45,7 @@ use ratatui::{ use tokio::sync::mpsc; use tracing::{debug, info}; -use crate::{components::wim_scan::WimScan, state::State, wim::parse_wim_file}; +use crate::{components::wim_scan::WimScan, state::State, wim::scan_local_drives}; pub struct App { // TUI @@ -144,11 +144,11 @@ impl App { ))?; } Mode::ScanWinImages => { - // TODO: DELETEME - let mut wim_sources = self.state.wim_sources.lock().unwrap(); - wim_sources - .local - .push(parse_wim_file("/home/twoshirt/Projects/deja-vu/23H2.wim")?); + let disk_list_arc = self.state.disk_list.clone(); + let wim_sources_arc = self.state.wim_sources.clone(); + tokio::task::spawn(async move { + scan_local_drives(disk_list_arc, wim_sources_arc); + }); } Mode::Done => { self.action_tx @@ -290,13 +290,6 @@ impl App { } Action::FindWimNetwork => { self.state.reset_network(); - let mut wim_sources = self.state.wim_sources.lock().unwrap(); - wim_sources - .network - .push(parse_wim_file("/home/twoshirt/Projects/deja-vu/23H2.wim")?); - wim_sources - .network - .push(parse_wim_file("/home/twoshirt/Projects/deja-vu/24H2.wim")?); // TODO: Actually scan network! } Action::NextScreen => { diff --git a/win_installer/src/components/wim_scan.rs b/win_installer/src/components/wim_scan.rs index 039177e..af7ad6d 100644 --- a/win_installer/src/components/wim_scan.rs +++ b/win_installer/src/components/wim_scan.rs @@ -95,47 +95,29 @@ impl Component for WimScan { .direction(Direction::Vertical) .constraints([Constraint::Length(1), Constraint::Min(1)]) .areas(right); - let [local_area, network_area] = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Percentage(50), Constraint::Percentage(50)]) - .areas(left_body); // Titles let titles = vec![ - Paragraph::new(Line::from("Scanning").centered()) + Paragraph::new(Line::from("Local").centered()) .block(Block::default().borders(Borders::NONE)), - Paragraph::new(Line::from("Info").centered()) + Paragraph::new(Line::from("Network").centered()) .block(Block::default().borders(Borders::NONE)), ]; for (title, area) in zip(titles, [left_title, right_title]) { frame.render_widget(title, area); } - // Local Scan - let local_area = if self.scan_network { - local_area - } else { - left_body - }; - let local_words = "Lorem ipsum dolor sit amet".split_whitespace().to_owned(); - let local_list = List::new(local_words) - .block( - Block::default() - .borders(Borders::ALL) - .padding(Padding::new(1, 1, 1, 1)), - ) - .highlight_spacing(HighlightSpacing::Always) - .highlight_style(Style::new().green().bold()) - .highlight_symbol(" --> ") - .repeat_highlight_symbol(false); - frame.render_widget(local_list, local_area); - - // Network Scan - if self.scan_network { - let network_words = "Adipiscing elit quisque faucibus ex sapien" - .split_whitespace() - .to_owned(); - let network_list = List::new(network_words) + // WIM Info + if let Ok(wim_sources) = self.wim_sources.lock() { + // Local + let mut left_list = Vec::new(); + left_list.extend( + wim_sources + .local + .iter() + .map(|wimfile| ListItem::new(format!("{}\n\n", wimfile.path))), + ); + let left_list = List::new(left_list) .block( Block::default() .borders(Borders::ALL) @@ -145,40 +127,28 @@ impl Component for WimScan { .highlight_style(Style::new().green().bold()) .highlight_symbol(" --> ") .repeat_highlight_symbol(false); - frame.render_widget(network_list, network_area); - } + frame.render_widget(left_list, left_body); - // WIM Info - let wim_sources = self.wim_sources.lock().unwrap(); - let mut right_list = Vec::new(); - if !wim_sources.network.is_empty() { - right_list.push(ListItem::new("-- Network --\n\n")); + // Network + let mut right_list = Vec::new(); right_list.extend( wim_sources .network .iter() .map(|wimfile| ListItem::new(format!("{}\n\n", wimfile.path))), ); - right_list.push(ListItem::new("")); + let right_list = List::new(right_list) + .block( + Block::default() + .borders(Borders::ALL) + .padding(Padding::new(1, 1, 1, 1)), + ) + .highlight_spacing(HighlightSpacing::Always) + .highlight_style(Style::new().green().bold()) + .highlight_symbol(" --> ") + .repeat_highlight_symbol(false); + frame.render_widget(right_list, right_body); } - right_list.push(ListItem::new("-- Local --\n\n")); - right_list.extend( - wim_sources - .local - .iter() - .map(|wimfile| ListItem::new(format!("{}\n\n", wimfile.path))), - ); - let right_list = List::new(right_list) - .block( - Block::default() - .borders(Borders::ALL) - .padding(Padding::new(1, 1, 1, 1)), - ) - .highlight_spacing(HighlightSpacing::Always) - .highlight_style(Style::new().green().bold()) - .highlight_symbol(" --> ") - .repeat_highlight_symbol(false); - frame.render_widget(right_list, right_body); // Done Ok(()) diff --git a/win_installer/src/state.rs b/win_installer/src/state.rs index 885485b..d85f8ba 100644 --- a/win_installer/src/state.rs +++ b/win_installer/src/state.rs @@ -37,8 +37,10 @@ pub struct State { impl State { pub fn new(disk_list: Arc>>) -> Self { + let wim_sources = WimSources::new(); State { disk_list, + wim_sources: Arc::new(Mutex::new(wim_sources)), ..Default::default() } } diff --git a/win_installer/src/wim.rs b/win_installer/src/wim.rs index 3e407be..7065d9c 100644 --- a/win_installer/src/wim.rs +++ b/win_installer/src/wim.rs @@ -1,3 +1,4 @@ +use core::system::disk::Disk; // This file is part of Deja-Vu. // // Deja-Vu is free software: you can redistribute it and/or modify it @@ -14,11 +15,17 @@ // along with Deja-Vu. If not, see . // use std::{ - collections::HashMap, fmt, fs::File, io::BufReader, path::Path, process::Command, - sync::LazyLock, + collections::HashMap, + fmt, + fs::{File, read_dir}, + io::BufReader, + path::Path, + process::Command, + sync::{Arc, LazyLock, Mutex}, }; use tempfile::NamedTempFile; +use tracing::info; use xml::reader::{EventReader, XmlEvent}; static WIN_BUILDS: LazyLock> = LazyLock::new(|| { @@ -139,13 +146,11 @@ pub fn parse_wim_file(wim_file: &str) -> std::io::Result { let mut image = WimImage::new(); let parser = EventReader::new(file); - let mut depth = 0; for e in parser { match e { Ok(XmlEvent::StartElement { name, attributes, .. }) => { - depth += 1; current_element = name.local_name.to_uppercase(); if current_element == "IMAGE" { @@ -171,8 +176,6 @@ pub fn parse_wim_file(wim_file: &str) -> std::io::Result { } } Ok(XmlEvent::EndElement { name }) => { - depth -= 1; - if name.local_name.to_uppercase() == "IMAGE" { // Append image to list if !image.build.is_empty() && !image.name.is_empty() && !image.index.is_empty() @@ -184,7 +187,7 @@ pub fn parse_wim_file(wim_file: &str) -> std::io::Result { image.reset() } } - Err(e) => { + Err(_) => { break; } _ => {} @@ -198,24 +201,37 @@ pub fn parse_wim_file(wim_file: &str) -> std::io::Result { Ok(wim_file) } -// fn main() -> std::io::Result<()> { -// let mut sources = WimSources::new(); -// if let Ok(wim_file) = parse_wim_file("./23H2.wim") -// && !wim_file.images.is_empty() -// { -// sources.local.push(wim_file); -// } -// if let Ok(wim_file) = parse_wim_file("./24H2.wim") { -// sources.local.push(wim_file); -// } -// dbg!(&sources); -// sources.local.iter().for_each(|f| { -// println!("-- {} --", f.path.to_string_lossy()); -// f.images.iter().for_each(|i| { -// println!("* {i}"); -// }); -// println!(); -// }); -// -// Ok(()) -// } +pub fn scan_local_drives( + disk_list_arc: Arc>>, + wim_sources_arc: Arc>, +) { + let mut to_check = vec![String::from(".")]; + + // Get drive letters + if let Ok(disk_list) = disk_list_arc.lock() { + disk_list.iter().for_each(|d| { + d.parts.iter().for_each(|p| { + if !p.letter.is_empty() { + to_check.push(format!("{}/Images", &p.letter)); + } + }); + }) + } + + // Scan drives + to_check.iter().for_each(|scan_path| { + info!("Scanning: {}", &scan_path); + if let Ok(read_dir) = read_dir(scan_path) { + read_dir.for_each(|item| { + if let Ok(item) = item + && item.file_name().to_string_lossy().ends_with(".wim") + && let Some(path_str) = item.path().to_str() + && let Ok(new_source) = parse_wim_file(path_str) + && let Ok(mut wim_sources) = wim_sources_arc.lock() + { + wim_sources.local.push(new_source); + } + }); + } + }); +}