From: Christoph Heiss Date: Fri, 10 Nov 2023 14:17:20 +0000 (+0100) Subject: tui: install_progress: move progress task into own function X-Git-Url: https://git.proxmox.com/?p=pve-installer.git;a=commitdiff_plain;h=c59da6c8167604b277504daacf3152af58d9170e tui: install_progress: move progress task into own function No functional changes. Signed-off-by: Christoph Heiss --- diff --git a/proxmox-tui-installer/src/views/install_progress.rs b/proxmox-tui-installer/src/views/install_progress.rs index 4dca81b..ccf53ad 100644 --- a/proxmox-tui-installer/src/views/install_progress.rs +++ b/proxmox-tui-installer/src/views/install_progress.rs @@ -10,7 +10,7 @@ use cursive::{ utils::Counter, view::{Resizable, ViewWrapper}, views::{Dialog, DummyView, LinearLayout, PaddedView, ProgressBar, TextContent, TextView}, - Cursive, + CbSink, Cursive, }; use crate::{abort_install_button, setup::InstallConfig, yes_no_dialog, InstallerState}; @@ -28,152 +28,7 @@ impl InstallProgressView { let progress_task = { let progress_text = progress_text.clone(); let state = state.clone(); - move |counter: Counter| { - let child = { - use std::process::{Command, Stdio}; - - let (path, args, envs): (&str, &[&str], Vec<(&str, &str)>) = - if state.in_test_mode { - ( - "./proxmox-low-level-installer", - &["-t", "start-session-test"], - vec![("PERL5LIB", ".")], - ) - } else { - ("proxmox-low-level-installer", &["start-session"], vec![]) - }; - - Command::new(path) - .args(args) - .envs(envs) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - }; - - let mut child = match child { - Ok(child) => child, - Err(err) => { - let _ = cb_sink.send(Box::new(move |siv| { - siv.add_layer( - Dialog::text(err.to_string()) - .title("Error") - .button("Ok", Cursive::quit), - ); - })); - return; - } - }; - - let inner = || { - let reader = child.stdout.take().map(BufReader::new)?; - let mut writer = child.stdin.take()?; - - serde_json::to_writer(&mut writer, &InstallConfig::from(state.options)) - .unwrap(); - writeln!(writer).unwrap(); - - let writer = Arc::new(Mutex::new(writer)); - - for line in reader.lines() { - let line = match line { - Ok(line) => line, - Err(_) => break, - }; - - let msg = match line.parse::() { - Ok(msg) => msg, - Err(stray) => { - eprintln!("low-level installer: {stray}"); - continue; - } - }; - - match msg { - UiMessage::Info(s) => cb_sink.send(Box::new(|siv| { - siv.add_layer(Dialog::info(s).title("Information")); - })), - UiMessage::Error(s) => cb_sink.send(Box::new(|siv| { - siv.add_layer(Dialog::info(s).title("Error")); - })), - UiMessage::Prompt(s) => cb_sink.send({ - let writer = writer.clone(); - Box::new(move |siv| { - yes_no_dialog( - siv, - "Prompt", - &s, - Box::new({ - let writer = writer.clone(); - move |_| { - if let Ok(mut writer) = writer.lock() { - let _ = writeln!(writer, "ok"); - } - } - }), - Box::new(move |_| { - if let Ok(mut writer) = writer.lock() { - let _ = writeln!(writer); - } - }), - ); - }) - }), - UiMessage::Progress(ratio, s) => { - counter.set(ratio); - progress_text.set_content(s); - Ok(()) - } - UiMessage::Finished(success, msg) => { - counter.set(100); - progress_text.set_content(msg.to_owned()); - cb_sink.send(Box::new(move |siv| { - let title = if success { "Success" } else { "Failure" }; - - // For rebooting, we just need to quit the installer, - // our caller does the actual reboot. - siv.add_layer( - Dialog::text(msg) - .title(title) - .button("Reboot now", Cursive::quit), - ); - - let autoreboot = siv - .user_data::() - .map(|state| state.options.autoreboot) - .unwrap_or_default(); - - if autoreboot && success { - let cb_sink = siv.cb_sink(); - thread::spawn({ - let cb_sink = cb_sink.clone(); - move || { - thread::sleep(Duration::from_secs(5)); - let _ = cb_sink.send(Box::new(Cursive::quit)); - } - }); - } - })) - } - } - .unwrap(); - } - - Some(()) - }; - - if inner().is_none() { - cb_sink - .send(Box::new(|siv| { - siv.add_layer( - Dialog::text("low-level installer exited early") - .title("Error") - .button("Exit", Cursive::quit), - ); - })) - .unwrap(); - } - } + move |counter: Counter| Self::progress_task(counter, cb_sink, state, progress_text) }; let progress_bar = ProgressBar::new().with_task(progress_task).full_width(); @@ -197,6 +52,156 @@ impl InstallProgressView { Self { view } } + + fn progress_task( + counter: Counter, + cb_sink: CbSink, + state: InstallerState, + progress_text: TextContent, + ) { + let child = { + use std::process::{Command, Stdio}; + + let (path, args, envs): (&str, &[&str], Vec<(&str, &str)>) = if state.in_test_mode { + ( + "./proxmox-low-level-installer", + &["-t", "start-session-test"], + vec![("PERL5LIB", ".")], + ) + } else { + ("proxmox-low-level-installer", &["start-session"], vec![]) + }; + + Command::new(path) + .args(args) + .envs(envs) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + }; + + let mut child = match child { + Ok(child) => child, + Err(err) => { + let _ = cb_sink.send(Box::new(move |siv| { + siv.add_layer( + Dialog::text(err.to_string()) + .title("Error") + .button("Ok", Cursive::quit), + ); + })); + return; + } + }; + + let inner = || { + let reader = child.stdout.take().map(BufReader::new)?; + let mut writer = child.stdin.take()?; + + serde_json::to_writer(&mut writer, &InstallConfig::from(state.options)).unwrap(); + writeln!(writer).unwrap(); + + let writer = Arc::new(Mutex::new(writer)); + + for line in reader.lines() { + let line = match line { + Ok(line) => line, + Err(_) => break, + }; + + let msg = match line.parse::() { + Ok(msg) => msg, + Err(stray) => { + eprintln!("low-level installer: {stray}"); + continue; + } + }; + + match msg { + UiMessage::Info(s) => cb_sink.send(Box::new(|siv| { + siv.add_layer(Dialog::info(s).title("Information")); + })), + UiMessage::Error(s) => cb_sink.send(Box::new(|siv| { + siv.add_layer(Dialog::info(s).title("Error")); + })), + UiMessage::Prompt(s) => cb_sink.send({ + let writer = writer.clone(); + Box::new(move |siv| { + yes_no_dialog( + siv, + "Prompt", + &s, + Box::new({ + let writer = writer.clone(); + move |_| { + if let Ok(mut writer) = writer.lock() { + let _ = writeln!(writer, "ok"); + } + } + }), + Box::new(move |_| { + if let Ok(mut writer) = writer.lock() { + let _ = writeln!(writer); + } + }), + ); + }) + }), + UiMessage::Progress(ratio, s) => { + counter.set(ratio); + progress_text.set_content(s); + Ok(()) + } + UiMessage::Finished(success, msg) => { + counter.set(100); + progress_text.set_content(msg.to_owned()); + cb_sink.send(Box::new(move |siv| { + let title = if success { "Success" } else { "Failure" }; + + // For rebooting, we just need to quit the installer, + // our caller does the actual reboot. + siv.add_layer( + Dialog::text(msg) + .title(title) + .button("Reboot now", Cursive::quit), + ); + + let autoreboot = siv + .user_data::() + .map(|state| state.options.autoreboot) + .unwrap_or_default(); + + if autoreboot && success { + let cb_sink = siv.cb_sink(); + thread::spawn({ + let cb_sink = cb_sink.clone(); + move || { + thread::sleep(Duration::from_secs(5)); + let _ = cb_sink.send(Box::new(Cursive::quit)); + } + }); + } + })) + } + } + .unwrap(); + } + + Some(()) + }; + + if inner().is_none() { + cb_sink + .send(Box::new(|siv| { + siv.add_layer( + Dialog::text("low-level installer exited early") + .title("Error") + .button("Exit", Cursive::quit), + ); + })) + .unwrap(); + } + } } impl ViewWrapper for InstallProgressView {