working
This commit is contained in:
parent
814554e208
commit
db62ec1d88
3 changed files with 39 additions and 41 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
pub fn get_md5sums() -> Result<String, Box<dyn std::error::Error>> {
|
use anyhow::Result;
|
||||||
let client = reqwest::blocking::Client::builder()
|
use reqwest::blocking::Client;
|
||||||
.redirect(reqwest::redirect::Policy::none())
|
use reqwest::redirect::Policy;
|
||||||
.build()?;
|
|
||||||
|
pub fn get_md5sums() -> Result<String> {
|
||||||
|
let client = Client::builder().redirect(Policy::none()).build()?;
|
||||||
let res = client
|
let res = client
|
||||||
.get("https://www.linuxfromscratch.org/~thomas/multilib-m32/md5sums")
|
.get("https://www.linuxfromscratch.org/~thomas/multilib-m32/md5sums")
|
||||||
.send()?
|
.send()?
|
||||||
|
|
|
||||||
67
src/tui.rs
67
src/tui.rs
|
|
@ -15,6 +15,8 @@ use ratatui::{
|
||||||
widgets::{Block, Borders, List, ListItem, ListState},
|
widgets::{Block, Borders, List, ListItem, ListState},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "tui")]
|
#[cfg(feature = "tui")]
|
||||||
|
use spinners::{Spinner, Spinners};
|
||||||
|
#[cfg(feature = "tui")]
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
env,
|
env,
|
||||||
|
|
@ -93,7 +95,7 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let mut mirrors_list: Vec<String> = Vec::new();
|
let mut mirrors_list: Vec<String> = Vec::new();
|
||||||
let mut selected_mirror: Option<String> = None;
|
let mut selected_mirror: Option<String> = None;
|
||||||
let log_messages: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
|
let log_messages: Arc<Mutex<Vec<String>>> = Arc::new(Mutex::new(Vec::new()));
|
||||||
let progress_state: Arc<Mutex<HashMap<String, String>>> =
|
let progress_state: Arc<Mutex<HashMap<String, Option<Spinner>>>> =
|
||||||
Arc::new(Mutex::new(HashMap::new()));
|
Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
let (tx, rx) = channel::<String>();
|
let (tx, rx) = channel::<String>();
|
||||||
|
|
@ -116,7 +118,6 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
)
|
)
|
||||||
.split(size);
|
.split(size);
|
||||||
|
|
||||||
// Render menu items
|
|
||||||
for (i, item) in menu_items.iter().enumerate() {
|
for (i, item) in menu_items.iter().enumerate() {
|
||||||
let style = if Some(i) == state.selected() {
|
let style = if Some(i) == state.selected() {
|
||||||
Style::default().bg(Color::Blue).fg(Color::White)
|
Style::default().bg(Color::Blue).fg(Color::White)
|
||||||
|
|
@ -130,7 +131,6 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render logs & progress
|
|
||||||
let logs = log_messages.lock().unwrap();
|
let logs = log_messages.lock().unwrap();
|
||||||
let mut combined_logs: Vec<ListItem> = logs
|
let mut combined_logs: Vec<ListItem> = logs
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -140,8 +140,13 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let progress = progress_state.lock().unwrap();
|
let progress = progress_state.lock().unwrap();
|
||||||
for (file, status) in progress.iter() {
|
for (file, spinner_opt) in progress.iter() {
|
||||||
combined_logs.push(ListItem::new(format!("{}: {}", file, status)));
|
let display_status = if let Some(spinner) = spinner_opt {
|
||||||
|
spinner.to_string()
|
||||||
|
} else {
|
||||||
|
"✅ Done".to_string()
|
||||||
|
};
|
||||||
|
combined_logs.push(ListItem::new(format!("{}: {}", file, display_status)));
|
||||||
}
|
}
|
||||||
|
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
|
|
@ -159,13 +164,11 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
KeyCode::Up => state.select(state.selected().map(|i| i.saturating_sub(1))),
|
KeyCode::Up => state.select(state.selected().map(|i| i.saturating_sub(1))),
|
||||||
KeyCode::Enter => match state.selected() {
|
KeyCode::Enter => match state.selected() {
|
||||||
Some(0) => {
|
Some(0) => {
|
||||||
// Init environment
|
|
||||||
let (path, msg) = init_environment();
|
let (path, msg) = init_environment();
|
||||||
lfs_sources = Some(path);
|
lfs_sources = Some(path);
|
||||||
log_messages.lock().unwrap().push(msg);
|
log_messages.lock().unwrap().push(msg);
|
||||||
}
|
}
|
||||||
Some(1) => {
|
Some(1) => {
|
||||||
// Mirror selection
|
|
||||||
if mirrors_list.is_empty() {
|
if mirrors_list.is_empty() {
|
||||||
mirrors_list = mirrors::fetch_mirrors().unwrap_or_else(|_| {
|
mirrors_list = mirrors::fetch_mirrors().unwrap_or_else(|_| {
|
||||||
vec![
|
vec![
|
||||||
|
|
@ -232,60 +235,52 @@ pub fn tui_menu() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(2) => {
|
Some(2) => {
|
||||||
// Download packages
|
|
||||||
if let Some(ref path) = lfs_sources {
|
if let Some(ref path) = lfs_sources {
|
||||||
let mirror: Option<String> = selected_mirror.clone(); // Correct Option<String>
|
let mirror = selected_mirror
|
||||||
log_messages.lock().unwrap().push(format!(
|
.clone()
|
||||||
"Using mirror: {}",
|
.unwrap_or_else(|| "ftp.fau.de".to_string());
|
||||||
mirror.clone().unwrap_or_else(|| "default mirror".into())
|
|
||||||
));
|
|
||||||
|
|
||||||
let path_clone = path.clone();
|
|
||||||
let log_clone = Arc::clone(&log_messages);
|
|
||||||
let tx_clone = tx.clone();
|
|
||||||
let wget_list = prepare_wget_list();
|
let wget_list = prepare_wget_list();
|
||||||
let md5_map = prepare_md5_map();
|
let md5_map = prepare_md5_map();
|
||||||
|
|
||||||
if wget_list.is_empty() {
|
if wget_list.is_empty() {
|
||||||
log_clone
|
log_messages
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push("⚠️ No packages to download!".into());
|
.push("⚠️ No packages to download!".into());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize progress
|
|
||||||
{
|
|
||||||
let mut prog = progress_state.lock().unwrap();
|
|
||||||
prog.clear();
|
|
||||||
for file in &wget_list {
|
|
||||||
prog.insert(file.clone(), "Pending".into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn download thread
|
|
||||||
let progress_clone = Arc::clone(&progress_state);
|
let progress_clone = Arc::clone(&progress_state);
|
||||||
|
let tx_clone = tx.clone();
|
||||||
|
let path_clone = path.clone();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
for file in wget_list {
|
for file in wget_list {
|
||||||
|
let spinner = Spinner::new(
|
||||||
|
Spinners::Dots9,
|
||||||
|
format!("Downloading {}", file),
|
||||||
|
);
|
||||||
progress_clone
|
progress_clone
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(file.clone(), "Downloading...".into());
|
.insert(file.clone(), Some(spinner));
|
||||||
|
|
||||||
let result = downloader::download_files(
|
let result = downloader::download_files(
|
||||||
&file,
|
&file,
|
||||||
&path_clone,
|
&path_clone,
|
||||||
mirror.clone(),
|
Some(mirror.clone()),
|
||||||
Some(&md5_map),
|
Some(&md5_map),
|
||||||
);
|
);
|
||||||
let status = match result {
|
|
||||||
Ok(_) => "✅ Done",
|
|
||||||
Err(_) => "❌ Failed",
|
|
||||||
};
|
|
||||||
progress_clone
|
progress_clone
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(file.clone(), status.to_string());
|
.insert(file.clone(), None);
|
||||||
let _ = tx_clone.send(format!("{} {}", status, file));
|
|
||||||
|
let status_msg = match result {
|
||||||
|
Ok(_) => format!("✅ {}", file),
|
||||||
|
Err(_) => format!("❌ {}", file),
|
||||||
|
};
|
||||||
|
let _ = tx_clone.send(status_msg);
|
||||||
}
|
}
|
||||||
let _ = tx_clone.send("🎉 All downloads complete!".into());
|
let _ = tx_clone.send("🎉 All downloads complete!".into());
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
use anyhow::Result;
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use reqwest::redirect::Policy;
|
use reqwest::redirect::Policy;
|
||||||
|
|
||||||
pub fn get_wget_list() -> Result<String, Box<dyn std::error::Error>> {
|
pub fn get_wget_list() -> Result<String> {
|
||||||
let client = Client::builder().redirect(Policy::none()).build()?;
|
let client = Client::builder().redirect(Policy::none()).build()?;
|
||||||
let res = client
|
let res = client
|
||||||
.get("https://www.linuxfromscratch.org/~thomas/multilib-m32/wget-list-sysv")
|
.get("https://www.linuxfromscratch.org/~thomas/multilib-m32/wget-list-sysv")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue