working
This commit is contained in:
parent
bc3560f1f8
commit
23905877c7
3 changed files with 162 additions and 60 deletions
29
src/main.rs
29
src/main.rs
|
|
@ -4,6 +4,9 @@ mod mirrors;
|
|||
mod version_check;
|
||||
mod wget_list;
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
mod tui; // Importiere das TUI-Modul, wenn das Feature aktiv ist
|
||||
|
||||
use console::style;
|
||||
use rand::Rng;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -11,6 +14,16 @@ use std::env;
|
|||
use std::path::PathBuf;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
#[cfg(feature = "tui")]
|
||||
{
|
||||
// Wenn das TUI-Feature aktiv ist, starte das TUI-Menü
|
||||
tui::tui_menu()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "tui"))]
|
||||
{
|
||||
// Wenn das TUI-Feature NICHT aktiv ist, führe die CLI-Logik aus
|
||||
// --- Run host system version checks ---
|
||||
if version_check::run_version_checks() {
|
||||
eprintln!(
|
||||
|
|
@ -29,8 +42,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let lfs_sources = match env::var("LFS") {
|
||||
Ok(lfs) => PathBuf::from(lfs).join("sources"),
|
||||
Err(_) => {
|
||||
let mut rng = rand::rng();
|
||||
let random_number: u32 = rng.random_range(1000..=9999);
|
||||
let mut rng = rand::thread_rng(); // Verwende thread_rng() statt rng()
|
||||
let random_number: u32 = rng.gen_range(1000..=9999); // Verwende gen_range() statt random_range()
|
||||
let tmp_path = format!("/tmp/lfs_{}", random_number);
|
||||
println!(
|
||||
"{} Using temporary path {}",
|
||||
|
|
@ -42,7 +55,16 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
};
|
||||
|
||||
// --- Choose mirror and fetch wget list ---
|
||||
let package_mirror = mirrors::choose_package_mirror();
|
||||
// Diese Zeile wird entfernt, da die Mirror-Auswahl in der TUI erfolgt
|
||||
// let package_mirror = mirrors::choose_package_mirror();
|
||||
|
||||
// Da die Mirror-Auswahl nun in der TUI erfolgt, müssen wir hier einen Standardwert oder eine andere Logik verwenden,
|
||||
// wenn das TUI nicht aktiv ist. Für dieses Beispiel nehmen wir an, dass wir keinen Mirror verwenden,
|
||||
// wenn das TUI nicht aktiv ist, oder wir könnten eine andere CLI-basierte Auswahl implementieren.
|
||||
// Für den Moment setzen wir es auf None, was bedeutet, dass der Standard-Mirror verwendet wird.
|
||||
let package_mirror: Option<String> = None;
|
||||
|
||||
|
||||
let wget_list = wget_list::get_wget_list()?;
|
||||
|
||||
// --- Prepare MD5 map ---
|
||||
|
|
@ -60,4 +82,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
|
||||
println!("{} All done!", style("🎉").green().bold());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ pub fn choose_package_mirror() -> Option<String> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fetch_mirrors() -> Result<Vec<String>, Box<dyn std::error::Error>> {
|
||||
pub fn fetch_mirrors() -> Result<Vec<String>, Box<dyn std::error::Error>> {
|
||||
let client = Client::new();
|
||||
let res = client
|
||||
.get("https://www.linuxfromscratch.org/lfs/mirrors.html#files")
|
||||
|
|
|
|||
115
src/tui.rs
115
src/tui.rs
|
|
@ -12,23 +12,31 @@ use ratatui::{
|
|||
backend::CrosstermBackend,
|
||||
layout::{Constraint, Direction, Layout},
|
||||
style::{Color, Style},
|
||||
widgets::{Block, Borders, List, ListItem, ListState},
|
||||
widgets::{Block, Borders, List, ListItem, ListState, Paragraph},
|
||||
};
|
||||
#[cfg(feature = "tui")]
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{self, stdout},
|
||||
io::stdout,
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
time::{Duration, Instant},
|
||||
fs, // Added for file system operations
|
||||
};
|
||||
#[cfg(feature = "tui")] // Hinzugefügt: Import des Rng-Traits
|
||||
use rand::Rng;
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
fn init_environment() -> PathBuf {
|
||||
let tmp_path = format!("/tmp/lfs_{}", rand::random::<u32>() % 9000 + 1000);
|
||||
println!("ℹ️ Using temporary path {}", tmp_path);
|
||||
PathBuf::from(tmp_path).join("sources")
|
||||
fn init_environment() -> Result<PathBuf, Box<dyn std::error::Error>> {
|
||||
let mut rng = rand::rng();
|
||||
let random_number: u32 = rng.gen_range(1000..=9999);
|
||||
let tmp_base_path = PathBuf::from(format!("/tmp/lfs_{}", random_number));
|
||||
let lfs_sources_path = tmp_base_path.join("sources");
|
||||
|
||||
std::fs::create_dir_all(&lfs_sources_path)?;
|
||||
|
||||
Ok(lfs_sources_path)
|
||||
}
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
|
|
@ -50,7 +58,7 @@ fn select_mirrors_tui(mirrors: Vec<String>) -> Vec<String> {
|
|||
loop {
|
||||
terminal
|
||||
.draw(|f| {
|
||||
let size = f.size();
|
||||
let size = f.area();
|
||||
let items: Vec<ListItem> = mirrors
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
|
@ -113,13 +121,12 @@ fn download_packages_tui(lfs_sources: &PathBuf) {
|
|||
let mirrors_list = mirrors::fetch_mirrors().unwrap_or_default();
|
||||
let selected_mirrors = select_mirrors_tui(mirrors_list);
|
||||
if selected_mirrors.is_empty() {
|
||||
println!("⚠️ No mirrors selected!");
|
||||
return;
|
||||
}
|
||||
|
||||
let wget_list = wget_list::get_wget_list().unwrap_or_default();
|
||||
let wget_list_content = wget_list::get_wget_list().unwrap_or_default();
|
||||
let wget_list: Vec<String> = wget_list_content.lines().map(|s| s.to_string()).collect();
|
||||
if wget_list.is_empty() {
|
||||
println!("⚠️ No packages to download!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +182,7 @@ fn download_packages_tui(lfs_sources: &PathBuf) {
|
|||
loop {
|
||||
terminal
|
||||
.draw(|f| {
|
||||
let size = f.size();
|
||||
let size = f.area();
|
||||
let items: Vec<ListItem> = {
|
||||
let state = download_state.lock().unwrap();
|
||||
state
|
||||
|
|
@ -201,7 +208,6 @@ fn download_packages_tui(lfs_sources: &PathBuf) {
|
|||
|
||||
disable_raw_mode().unwrap();
|
||||
execute!(terminal.backend_mut(), LeaveAlternateScreen).unwrap();
|
||||
println!("🎉 All downloads finished!");
|
||||
}
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
|
|
@ -216,16 +222,19 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
|||
"🌱 Init environment",
|
||||
"📦 Download packages",
|
||||
"🔍 Check status",
|
||||
"🧹 Clean up temp directories", // Neuer Menüpunkt
|
||||
"❌ Exit",
|
||||
];
|
||||
let mut state = ListState::default();
|
||||
state.select(Some(0));
|
||||
|
||||
let mut lfs_sources: Option<PathBuf> = None;
|
||||
let mut status_message: Option<String> = None; // Für Statusmeldungen
|
||||
let mut status_message_timer: Option<std::time::Instant> = None; // Für temporäre Meldungen
|
||||
|
||||
loop {
|
||||
terminal.draw(|f| {
|
||||
let size = f.size();
|
||||
let size = f.area();
|
||||
let block = Block::default()
|
||||
.title("✨ lpkg TUI 🌈")
|
||||
.borders(Borders::ALL);
|
||||
|
|
@ -246,8 +255,35 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
|||
let list = List::new(vec![list_item]).block(Block::default().borders(Borders::ALL));
|
||||
f.render_widget(list, chunks[i]);
|
||||
}
|
||||
|
||||
// Statusmeldung anzeigen
|
||||
if let Some(msg) = &status_message {
|
||||
let msg_block = Block::default()
|
||||
.borders(Borders::NONE)
|
||||
.style(Style::default().fg(Color::Yellow));
|
||||
let paragraph = Paragraph::new(msg.as_str()).block(msg_block);
|
||||
// Positionierung der Statusmeldung (z.B. unten in der Mitte)
|
||||
let msg_area = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Percentage(10), Constraint::Percentage(80), Constraint::Percentage(10)])
|
||||
.split(size)[1]; // Mittlerer Bereich
|
||||
let msg_area = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Min(0), Constraint::Length(1)])
|
||||
.split(msg_area)[1]; // Unterste Zeile
|
||||
f.render_widget(paragraph, msg_area);
|
||||
}
|
||||
})?;
|
||||
|
||||
// Statusmeldung nach einer bestimmten Zeit ausblenden
|
||||
if let Some(timer) = status_message_timer {
|
||||
if timer.elapsed() > Duration::from_secs(3) { // 3 Sekunden anzeigen
|
||||
status_message = None;
|
||||
status_message_timer = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if let Event::Key(key) = event::read()? {
|
||||
match key.code {
|
||||
KeyCode::Down => {
|
||||
|
|
@ -264,19 +300,44 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
KeyCode::Enter => match state.selected() {
|
||||
Some(0) => {
|
||||
lfs_sources = Some(init_environment());
|
||||
match init_environment() {
|
||||
Ok(path) => {
|
||||
lfs_sources = Some(path.clone());
|
||||
status_message = Some(format!("✅ Environment initialized: {}", path.display()));
|
||||
}
|
||||
Err(e) => {
|
||||
status_message = Some(format!("❌ Failed to initialize environment: {}", e));
|
||||
}
|
||||
}
|
||||
status_message_timer = Some(std::time::Instant::now());
|
||||
}
|
||||
Some(1) => {
|
||||
if let Some(ref path) = lfs_sources {
|
||||
download_packages_tui(path);
|
||||
} else {
|
||||
println!("⚠️ Please initialize environment first!");
|
||||
status_message = Some("⚠️ Please initialize environment first!".to_string());
|
||||
status_message_timer = Some(std::time::Instant::now());
|
||||
}
|
||||
}
|
||||
Some(2) => {
|
||||
println!("🔍 Status selected! (TODO)");
|
||||
status_message = Some("🔍 Status selected! (TODO)".to_string());
|
||||
status_message_timer = Some(std::time::Instant::now());
|
||||
}
|
||||
Some(3) | _ => break,
|
||||
Some(3) => {
|
||||
// Aufruf der neuen Bereinigungsfunktion
|
||||
status_message = Some("🧹 Cleaning up temporary directories...".to_string());
|
||||
status_message_timer = Some(std::time::Instant::now());
|
||||
match cleanup_temp_directories() {
|
||||
Ok(count) => {
|
||||
status_message = Some(format!("✅ Cleaned up {} temporary directories.", count));
|
||||
}
|
||||
Err(e) => {
|
||||
status_message = Some(format!("❌ Failed to clean up: {}", e));
|
||||
}
|
||||
}
|
||||
status_message_timer = Some(std::time::Instant::now());
|
||||
}
|
||||
Some(4) | _ => break,
|
||||
},
|
||||
KeyCode::Esc => break,
|
||||
_ => {}
|
||||
|
|
@ -289,3 +350,21 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
|||
terminal.show_cursor()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
fn cleanup_temp_directories() -> Result<usize, Box<dyn std::error::Error>> {
|
||||
let mut cleaned_count = 0;
|
||||
for entry in std::fs::read_dir("/tmp")? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
if let Some(dir_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
if dir_name.starts_with("lfs_") {
|
||||
std::fs::remove_dir_all(&path)?;
|
||||
cleaned_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(cleaned_count)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue