Add CommandExt trait (#146)

* Color CI output

* Improve `CommandExt`

* Add comments explaining `#[allow]`s

* Remove useless `dead_code` annotation

* Improve error messages

* Print errors when running a shell errors

* fixup! Remove useless `dead_code` annotation
This commit is contained in:
Rebecca Turner
2022-11-08 05:54:35 -05:00
committed by Thomas Schönauer
parent bd34a3bcd4
commit e84173be8f
32 changed files with 822 additions and 558 deletions

View File

@@ -7,6 +7,7 @@ use std::process::Command;
use std::sync::Mutex;
use std::time::Duration;
use anyhow::Context;
use chrono::{Local, Timelike};
use console::{style, Key, Term};
use lazy_static::lazy_static;
@@ -16,6 +17,7 @@ use notify_rust::{Notification, Timeout};
#[cfg(windows)]
use which_crate::which;
use crate::command::CommandExt;
use crate::report::StepResult;
#[cfg(target_os = "linux")]
use crate::utils::which;
@@ -34,13 +36,8 @@ pub fn shell() -> &'static str {
which("pwsh").map(|_| "pwsh").unwrap_or("powershell")
}
pub fn run_shell() {
Command::new(shell())
.env("IN_TOPGRADE", "1")
.spawn()
.unwrap()
.wait()
.unwrap();
pub fn run_shell() -> anyhow::Result<()> {
Command::new(shell()).env("IN_TOPGRADE", "1").status_checked()
}
struct Terminal {
@@ -106,7 +103,9 @@ impl Terminal {
}
command.args(["-a", "Topgrade", "Topgrade"]);
command.arg(message.as_ref());
command.output().ok();
if let Err(err) = command.output_checked() {
log::error!("{err:?}");
}
}
}
}
@@ -214,7 +213,7 @@ impl Terminal {
}
}
#[allow(unused_variables)]
fn should_retry(&mut self, interrupted: bool, step_name: &str) -> Result<bool, io::Error> {
fn should_retry(&mut self, interrupted: bool, step_name: &str) -> anyhow::Result<bool> {
if self.width.is_none() {
return Ok(false);
}
@@ -225,29 +224,31 @@ impl Terminal {
self.notify_desktop(format!("{} failed", step_name), None);
self.term
.write_fmt(format_args!(
"\n{}",
style(format!("{}Retry? (y)es/(N)o/(s)hell/(q)uit", self.prefix))
.yellow()
.bold()
))
.ok();
let prompt_inner = style(format!("{}Retry? (y)es/(N)o/(s)hell/(q)uit", self.prefix))
.yellow()
.bold();
self.term.write_fmt(format_args!("\n{}", prompt_inner)).ok();
let answer = loop {
match self.term.read_key() {
Ok(Key::Char('y')) | Ok(Key::Char('Y')) => break Ok(true),
Ok(Key::Char('s')) | Ok(Key::Char('S')) => {
println!("\n\nDropping you to shell. Fix what you need and then exit the shell.\n");
run_shell();
break Ok(true);
if let Err(err) = run_shell().context("Failed to run shell") {
self.term.write_fmt(format_args!("{err:?}\n{}", prompt_inner)).ok();
} else {
break Ok(true);
}
}
Ok(Key::Char('n')) | Ok(Key::Char('N')) | Ok(Key::Enter) => break Ok(false),
Err(e) => {
error!("Error reading from terminal: {}", e);
break Ok(false);
}
Ok(Key::Char('q')) | Ok(Key::Char('Q')) => return Err(io::Error::from(io::ErrorKind::Interrupted)),
Ok(Key::Char('q')) | Ok(Key::Char('Q')) => {
return Err(io::Error::from(io::ErrorKind::Interrupted)).context("Quit from user input")
}
_ => (),
}
};
@@ -268,7 +269,7 @@ impl Default for Terminal {
}
}
pub fn should_retry(interrupted: bool, step_name: &str) -> Result<bool, io::Error> {
pub fn should_retry(interrupted: bool, step_name: &str) -> anyhow::Result<bool> {
TERMINAL.lock().unwrap().should_retry(interrupted, step_name)
}