2025-09-30 16:51:03 +02:00
|
|
|
use console::Style;
|
2025-09-30 17:08:26 +02:00
|
|
|
use reqwest::blocking::Client;
|
|
|
|
|
use scraper::{Html, Selector};
|
2025-09-30 16:51:03 +02:00
|
|
|
use std::io::{self, Write};
|
|
|
|
|
|
|
|
|
|
pub fn choose_package_mirror() -> Option<String> {
|
2025-09-30 17:08:26 +02:00
|
|
|
let mirrors = match fetch_mirrors() {
|
|
|
|
|
Ok(mirrors) => mirrors,
|
|
|
|
|
Err(e) => {
|
|
|
|
|
println!("Failed to fetch mirrors: {}", e);
|
|
|
|
|
// Fallback to a default list if fetching fails
|
|
|
|
|
vec!["ftp.fau.de".to_string(), "mirror.kernel.org".to_string(), "mirror.example.org".to_string()]
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-09-30 16:51:03 +02:00
|
|
|
|
|
|
|
|
println!("Optional: choose a mirror for GNU source packages (replace ftp.gnu.org):");
|
|
|
|
|
|
|
|
|
|
for (i, mirror) in mirrors.iter().enumerate() {
|
|
|
|
|
println!(" [{}] {}", i + 1, mirror);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
print!("Enter number or press Enter for default: ");
|
|
|
|
|
io::stdout().flush().unwrap();
|
|
|
|
|
|
|
|
|
|
let mut input = String::new();
|
|
|
|
|
io::stdin().read_line(&mut input).unwrap();
|
|
|
|
|
let input = input.trim();
|
|
|
|
|
|
|
|
|
|
if input.is_empty() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
let choice = input.parse::<usize>().unwrap_or(1);
|
|
|
|
|
let chosen = mirrors.get(choice.saturating_sub(1)).unwrap_or(&mirrors[0]);
|
|
|
|
|
println!(
|
|
|
|
|
"Using package mirror: {}",
|
|
|
|
|
Style::new().green().apply_to(chosen)
|
|
|
|
|
);
|
|
|
|
|
Some(chosen.to_string())
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-30 17:08:26 +02:00
|
|
|
|
|
|
|
|
fn fetch_mirrors() -> Result<Vec<String>, Box<dyn std::error::Error>> {
|
|
|
|
|
let client = Client::new();
|
|
|
|
|
// Fetching from the LFS mirrors page as it lists mirrors for various projects, including GNU
|
|
|
|
|
let res = client.get("https://www.linuxfromscratch.org/lfs/mirrors.html#files").send()?.text()?;
|
|
|
|
|
let document = Html::parse_document(&res);
|
|
|
|
|
// This selector targets links that are likely to be mirrors. Adjust if needed.
|
|
|
|
|
let selector = Selector::parse("a[href^='http']").unwrap();
|
|
|
|
|
let mirrors = document
|
|
|
|
|
.select(&selector)
|
|
|
|
|
.filter_map(|element| {
|
|
|
|
|
let href = element.value().attr("href")?;
|
|
|
|
|
// Basic filtering to get potential mirror URLs
|
|
|
|
|
if href.contains("ftp.gnu.org") || href.contains("mirror") {
|
|
|
|
|
Some(href.to_string())
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
Ok(mirrors)
|
|
|
|
|
}
|