feat: print summary and run post commands when (q)uit is used (#1254)

This commit is contained in:
Gideon
2025-11-15 10:03:46 +01:00
committed by GitHub
parent ea2ccdd69f
commit 639d055f9a
3 changed files with 52 additions and 24 deletions

View File

@@ -209,7 +209,19 @@ fn run() -> Result<()> {
} }
for step in step::default_steps() { for step in step::default_steps() {
step.run(&mut runner, &ctx)? match step.run(&mut runner, &ctx) {
Ok(()) => (),
Err(error)
if error
.downcast_ref::<io::Error>()
.is_some_and(|e| e.kind() == io::ErrorKind::Interrupted) =>
{
println!();
debug!("Interrupted (possibly with 'q' during retry prompt). Printing summary.");
break;
}
Err(error) => return Err(error),
}
} }
let mut failed = false; let mut failed = false;

View File

@@ -1,14 +1,15 @@
use color_eyre::eyre::Result; use color_eyre::eyre::{Result, WrapErr};
use rust_i18n::t; use rust_i18n::t;
use std::borrow::Cow; use std::borrow::Cow;
use std::fmt::Debug; use std::fmt::Debug;
use std::io;
use tracing::debug; use tracing::debug;
use crate::ctrlc; use crate::ctrlc;
use crate::error::{DryRun, MissingSudo, SkipStep}; use crate::error::{DryRun, MissingSudo, SkipStep};
use crate::execution_context::ExecutionContext; use crate::execution_context::ExecutionContext;
use crate::step::Step; use crate::step::Step;
use crate::terminal::{print_error, print_warning, should_retry}; use crate::terminal::{print_error, print_warning, should_retry, ShouldRetry};
pub enum StepResult { pub enum StepResult {
Success, Success,
@@ -98,21 +99,28 @@ impl<'a> Runner<'a> {
let should_ask = interrupted || !(self.ctx.config().no_retry() || ignore_failure); let should_ask = interrupted || !(self.ctx.config().no_retry() || ignore_failure);
let should_retry = if should_ask { let should_retry = if should_ask {
print_error(&key, format!("{e:?}")); print_error(&key, format!("{e:?}"));
should_retry(interrupted, key.as_ref())? should_retry(key.as_ref())?
} else { } else {
false ShouldRetry::No
}; };
if !should_retry { match should_retry {
self.push_result( ShouldRetry::No | ShouldRetry::Quit => {
key, self.push_result(
if ignore_failure { key,
StepResult::Ignored if ignore_failure {
} else { StepResult::Ignored
StepResult::Failure } else {
}, StepResult::Failure
); },
break; );
if let ShouldRetry::Quit = should_retry {
return Err(io::Error::from(io::ErrorKind::Interrupted))
.context("Quit from user input");
}
break;
}
ShouldRetry::Yes => (),
} }
} }
} }

View File

@@ -201,10 +201,11 @@ impl Terminal {
} }
} }
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn should_retry(&mut self, interrupted: bool, step_name: &str) -> eyre::Result<bool> { fn should_retry(&mut self, step_name: &str) -> eyre::Result<ShouldRetry> {
if self.width.is_none() { if self.width.is_none() {
return Ok(false); return Ok(ShouldRetry::No);
} }
if self.set_title { if self.set_title {
@@ -223,7 +224,7 @@ impl Terminal {
let answer = loop { let answer = loop {
match self.term.read_key() { match self.term.read_key() {
Ok(Key::Char('y' | 'Y')) => break Ok(true), Ok(Key::Char('y' | 'Y')) => break Ok(ShouldRetry::Yes),
Ok(Key::Char('s' | 'S')) => { Ok(Key::Char('s' | 'S')) => {
println!( println!(
"\n\n{}\n", "\n\n{}\n",
@@ -232,16 +233,16 @@ impl Terminal {
if let Err(err) = run_shell().context("Failed to run shell") { if let Err(err) = run_shell().context("Failed to run shell") {
self.term.write_fmt(format_args!("{err:?}\n{prompt_inner}")).ok(); self.term.write_fmt(format_args!("{err:?}\n{prompt_inner}")).ok();
} else { } else {
break Ok(true); break Ok(ShouldRetry::Yes);
} }
} }
Ok(Key::Char('n' | 'N') | Key::Enter) => break Ok(false), Ok(Key::Char('n' | 'N') | Key::Enter) => break Ok(ShouldRetry::No),
Err(e) => { Err(e) => {
error!("Error reading from terminal: {}", e); error!("Error reading from terminal: {}", e);
break Ok(false); break Ok(ShouldRetry::No);
} }
Ok(Key::Char('q' | 'Q')) => { Ok(Key::Char('q' | 'Q')) => {
return Err(io::Error::from(io::ErrorKind::Interrupted)).context("Quit from user input") break Ok(ShouldRetry::Quit);
} }
_ => (), _ => (),
} }
@@ -257,14 +258,21 @@ impl Terminal {
} }
} }
#[derive(Clone, Copy)]
pub enum ShouldRetry {
Yes,
No,
Quit,
}
impl Default for Terminal { impl Default for Terminal {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
pub fn should_retry(interrupted: bool, step_name: &str) -> eyre::Result<bool> { pub fn should_retry(step_name: &str) -> eyre::Result<ShouldRetry> {
TERMINAL.lock().unwrap().should_retry(interrupted, step_name) TERMINAL.lock().unwrap().should_retry(step_name)
} }
pub fn print_separator<P: AsRef<str>>(message: P) { pub fn print_separator<P: AsRef<str>>(message: P) {