This commit is contained in:
Lucy 2025-09-30 20:54:25 +02:00
parent 79219e7f81
commit 1eb7d4c1eb
4 changed files with 44 additions and 16 deletions

7
Cargo.lock generated
View file

@ -1364,6 +1364,7 @@ dependencies = [
"regex", "regex",
"reqwest", "reqwest",
"scraper", "scraper",
"semver",
"serde", "serde",
"serde_json", "serde_json",
"spinners", "spinners",
@ -1934,6 +1935,12 @@ dependencies = [
"smallvec", "smallvec",
] ]
[[package]]
name = "semver"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.228" version = "1.0.228"

View file

@ -32,6 +32,7 @@ md5 = "0.8.0"
# HTTP # HTTP
reqwest = { version = "0.12.23", features = ["blocking", "json"] } reqwest = { version = "0.12.23", features = ["blocking", "json"] }
semver = "1.0.27"
[features] [features]
# TUI feature flag # TUI feature flag

View file

@ -19,16 +19,23 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
{ {
// TUI-Modus // TUI-Modus
tui::tui_menu()?; tui::tui_menu()?;
Ok(()) return Ok(());
} }
#[cfg(not(feature = "tui"))] #[cfg(not(feature = "tui"))]
{ {
// --- Dynamische Version-Prüfung aus HTML --- // --- Dynamische Version-Prüfung direkt aus HTML ---
let json = html::fetch_and_parse_html_to_json( let ok = version_check::run_version_checks_from_html(
"https://www.linuxfromscratch.org/~thomas/multilib-m32/chapter02/hostreqs.html", "https://www.linuxfromscratch.org/~thomas/multilib-m32/chapter02/hostreqs.html",
)?; )?;
version_check::run_version_checks_from_json(&json);
if !ok {
eprintln!(
"{} Some version checks failed. Exiting.",
style("").red().bold()
);
std::process::exit(1);
}
println!( println!(
"{} All version checks passed. Starting downloader...", "{} All version checks passed. Starting downloader...",

View file

@ -1,5 +1,6 @@
use reqwest; use reqwest;
use scraper::{Html, Selector}; use scraper::{Html, Selector};
use semver::Version;
use std::process::Command; use std::process::Command;
/// Führt ein Kommando aus und gibt die erste Zeile der Version zurück /// Führt ein Kommando aus und gibt die erste Zeile der Version zurück
@ -12,8 +13,18 @@ fn run_command(cmd: &str, args: &[&str]) -> Option<String> {
} }
} }
/// Vergleicht zwei Versionen /// Vergleicht zwei Versionen mit semver (für Programme)
fn check_version(installed: &str, required: &str) -> bool { fn check_version(installed: &str, required: &str) -> bool {
let i = Version::parse(installed).ok();
let r = Version::parse(required).ok();
match (i, r) {
(Some(i), Some(r)) => i >= r,
_ => false,
}
}
/// Vergleicht Kernel-Versionen (numerisch)
fn check_kernel_version(installed: &str, required: &str) -> bool {
let parse_ver = |v: &str| { let parse_ver = |v: &str| {
v.split(['.', '-']) v.split(['.', '-'])
.filter_map(|s| s.parse::<u32>().ok()) .filter_map(|s| s.parse::<u32>().ok())
@ -48,7 +59,7 @@ fn ver_check(program: &str, cmd: &str, min_version: &str) -> bool {
println!("OK: {:<12} {:<8} >= {}", program, ver, min_version); println!("OK: {:<12} {:<8} >= {}", program, ver, min_version);
true true
} else { } else {
println!( eprintln!(
"ERROR: {:<12} version {} is too old ({} required)", "ERROR: {:<12} version {} is too old ({} required)",
program, ver, min_version program, ver, min_version
); );
@ -56,7 +67,7 @@ fn ver_check(program: &str, cmd: &str, min_version: &str) -> bool {
} }
} }
None => { None => {
println!("ERROR: Cannot find {}", program); eprintln!("ERROR: Cannot find {}", program);
false false
} }
} }
@ -65,11 +76,11 @@ fn ver_check(program: &str, cmd: &str, min_version: &str) -> bool {
/// Führt die Kernel-Prüfung durch /// Führt die Kernel-Prüfung durch
fn ver_kernel(min_version: &str) -> bool { fn ver_kernel(min_version: &str) -> bool {
let kernel = run_command("uname", &["-r"]).unwrap_or_default(); let kernel = run_command("uname", &["-r"]).unwrap_or_default();
if check_version(&kernel, min_version) { if check_kernel_version(&kernel, min_version) {
println!("OK: Linux Kernel {} >= {}", kernel, min_version); println!("OK: Linux Kernel {} >= {}", kernel, min_version);
true true
} else { } else {
println!( eprintln!(
"ERROR: Linux Kernel {} is too old ({} required)", "ERROR: Linux Kernel {} is too old ({} required)",
kernel, min_version kernel, min_version
); );
@ -78,7 +89,7 @@ fn ver_kernel(min_version: &str) -> bool {
} }
/// Lädt die LFS-Seite und führt alle Versionsprüfungen aus /// Lädt die LFS-Seite und führt alle Versionsprüfungen aus
pub fn run_version_checks_from_html(url: &str) -> Result<(), Box<dyn std::error::Error>> { pub fn run_version_checks_from_html(url: &str) -> Result<bool, Box<dyn std::error::Error>> {
let html_text = reqwest::blocking::get(url)?.text()?; let html_text = reqwest::blocking::get(url)?.text()?;
let document = Html::parse_document(&html_text); let document = Html::parse_document(&html_text);
let selector = Selector::parse("pre").unwrap(); let selector = Selector::parse("pre").unwrap();
@ -112,7 +123,7 @@ pub fn run_version_checks_from_html(url: &str) -> Result<(), Box<dyn std::error:
if output.to_lowercase().contains(&expected.to_lowercase()) { if output.to_lowercase().contains(&expected.to_lowercase()) {
println!("OK: {:<4} is {}", cmd, expected); println!("OK: {:<4} is {}", cmd, expected);
} else { } else {
println!("ERROR: {:<4} is NOT {}", cmd, expected); eprintln!("ERROR: {:<4} is NOT {}", cmd, expected);
} }
} }
}; };
@ -122,23 +133,25 @@ pub fn run_version_checks_from_html(url: &str) -> Result<(), Box<dyn std::error:
alias_check("sh", "Bash"); alias_check("sh", "Bash");
// Compiler-Test // Compiler-Test
if run_command("g++", &["-x", "c++", "-"]).is_some() { if run_command("g++", &["--version"]).is_some() {
println!("OK: g++ works"); println!("OK: g++ works");
} else { } else {
println!("ERROR: g++ does NOT work"); eprintln!("ERROR: g++ does NOT work");
ok = false;
} }
// nproc-Test // nproc-Test
let nproc = run_command("nproc", &[]).unwrap_or_default(); let nproc = run_command("nproc", &[]).unwrap_or_default();
if nproc.is_empty() { if nproc.is_empty() {
println!("ERROR: nproc is not available or empty"); eprintln!("ERROR: nproc is not available or empty");
ok = false;
} else { } else {
println!("OK: nproc reports {} logical cores available", nproc); println!("OK: nproc reports {} logical cores available", nproc);
} }
if !ok { if !ok {
println!("Some version checks failed."); eprintln!("Some version checks failed.");
} }
Ok(()) Ok(ok)
} }