diff --git a/locales/app.yml b/locales/app.yml index 0c924570..496908fb 100644 --- a/locales/app.yml +++ b/locales/app.yml @@ -1138,14 +1138,46 @@ _version: 2 zh_CN: "Topgrade 不应以 root 身份运行,它会在需要时使用 sudo 或等效工具执行命令。" zh_TW: "Topgrade 不應以 root 身份執行,它會在需要時使用 sudo 或等效工具執行命令。" de: "Topgrade sollte nicht als Root ausgeführt werden, es führt Befehle mit sudo oder einem Äquivalent aus, wenn erforderlich." -"Require sudo or counterpart but not found, skip": - en: "Require sudo or counterpart but not found, skip" - lt: "Reikalingas sudo arba atitikmuo, bet nerasta, praleidžiama" - es: "Se requiere sudo o su equivalente pero no ha sido encontrado, omitiendo" - fr: "Nécessite sudo ou un équivalent mais n'a pas été trouvé, passé" - zh_CN: "找不到权限管理程序(sudo 等),跳过" - zh_TW: "找不到權限管理程式(sudo 等),略過" - de: "Benötigt sudo oder Äquivalent, aber nicht gefunden, überspringe" +"Could not find sudo": + en: "Could not find sudo" + lt: "Nepavyko rasti sudo" + es: "No se pudo encontrar sudo" + fr: "Impossible de trouver sudo" + zh_CN: "未找到 sudo" + zh_TW: "找不到 sudo" + de: "Konnte sudo nicht finden" +"Skipping step, sudo is required": + en: "Skipping step, sudo is required" + lt: "Žingsnis praleidžiamas, reikalingas sudo" + es: "Omitiendo paso, se requiere sudo" + fr: "Étape ignorée, sudo est requis" + zh_CN: "跳过步骤,需要 sudo" + zh_TW: "跳過步驟,需要 sudo" + de: "Schritt wird übersprungen, sudo ist erforderlich" +"\nSome steps were skipped as sudo or equivalent could not be found.": + en: "\nSome steps were skipped as sudo or equivalent could not be found." + lt: "\nKai kurie veiksmai buvo praleisti, nes nepavyko rasti sudo ar atitikmens." + es: "\nAlgunos pasos se omitieron porque no se pudo encontrar sudo o equivalente." + fr: "\nCertaines étapes ont été ignorées car sudo ou équivalent est introuvable." + zh_CN: "\n由于未找到 sudo 或等效工具,某些步骤被跳过。" + zh_TW: "\n由於找不到 sudo 或等效工具,某些步驟已跳過。" + de: "\nEinige Schritte wurden übersprungen, da sudo oder ein Äquivalent nicht gefunden wurde." +"Install one of `sudo`, `doas`, `pkexec`, `run0` or `please` to run these steps.": + en: "Install one of `sudo`, `doas`, `pkexec`, `run0` or `please` to run these steps." + lt: "Įdiekite vieną iš `sudo`, `doas`, `pkexec`, `run0` arba `please`, kad vykdytumėte šiuos veiksmus." + es: "Instale uno de `sudo`, `doas`, `pkexec`, `run0` o `please` para ejecutar estos pasos." + fr: "Installez l’un de `sudo`, `doas`, `pkexec`, `run0` ou `please` pour exécuter ces étapes." + zh_CN: "请安装 `sudo`、`doas`、`pkexec`、`run0` 或 `please` 之一来运行这些步骤。" + zh_TW: "請安裝 `sudo`、`doas`、`pkexec`、`run0` 或 `please` 之一來執行這些步驟。" + de: "Installieren Sie `sudo`, `doas`, `pkexec`, `run0` oder `please`, um diese Schritte auszuführen." +"Install gsudo or enable Windows Sudo to run these steps.": + en: "Install gsudo or enable Windows Sudo to run these steps." + lt: "Įdiekite gsudo arba įjunkite Windows Sudo, kad vykdytumėte šiuos veiksmus." + es: "Instale gsudo o habilite Windows Sudo para ejecutar estos pasos." + fr: "Installez gsudo ou activez Windows Sudo pour exécuter ces étapes." + zh_CN: "请安装 gsudo 或启用 Windows Sudo 来运行这些步骤。" + zh_TW: "請安裝 gsudo 或啟用 Windows Sudo 來執行這些步驟。" + de: "Installieren Sie gsudo oder aktivieren Sie Windows Sudo, um diese Schritte auszuführen." "{sudo_kind} does not support the {option} option": en: "%{sudo_kind} does not support the %{option} option" lt: "%{sudo_kind} nepalaiko parinkties %{option}" diff --git a/src/error.rs b/src/error.rs index 748edde5..78a06845 100644 --- a/src/error.rs +++ b/src/error.rs @@ -90,6 +90,15 @@ impl Display for UnsupportedSudo<'_> { } } +#[derive(Error, Debug)] +pub struct MissingSudo(); + +impl Display for MissingSudo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", t!("Could not find sudo")) + } +} + #[derive(Error, Debug)] pub struct DryRun(); diff --git a/src/execution_context.rs b/src/execution_context.rs index c5cd15c2..808a9976 100644 --- a/src/execution_context.rs +++ b/src/execution_context.rs @@ -6,13 +6,14 @@ use std::ffi::OsStr; use std::process::Command; use std::sync::{LazyLock, Mutex}; -use crate::executor::DryCommand; +use crate::config::Config; +use crate::error::MissingSudo; +use crate::executor::{DryCommand, Executor}; use crate::powershell::Powershell; #[cfg(target_os = "linux")] use crate::steps::linux::Distribution; use crate::sudo::Sudo; use crate::utils::require_option; -use crate::{config::Config, executor::Executor}; /// An enum telling whether Topgrade should perform dry runs or actually perform the steps. #[derive(Clone, Copy, Debug)] @@ -95,10 +96,11 @@ impl<'a> ExecutionContext<'a> { } pub fn require_sudo(&self) -> Result<&Sudo> { - require_option( - self.sudo.as_ref(), - t!("Require sudo or counterpart but not found, skip").to_string(), - ) + if let Some(value) = self.sudo() { + Ok(value) + } else { + Err(MissingSudo().into()) + } } pub fn config(&self) -> &Config { diff --git a/src/main.rs b/src/main.rs index 8f20d080..7191db01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ use self::config::{CommandLineArgs, Config}; use self::error::StepFailed; #[cfg(all(windows, feature = "self-update"))] use self::error::Upgraded; +use self::runner::StepResult; #[allow(clippy::wildcard_imports)] use self::steps::{remote::*, *}; use self::sudo::{Sudo, SudoKind}; @@ -224,12 +225,30 @@ fn run() -> Result<()> { if !report.is_empty() { print_separator(t!("Summary")); + let mut skipped_missing_sudo = false; + for (key, result) in report { if !failed && result.failed() { failed = true; } + if let StepResult::SkippedMissingSudo = result { + skipped_missing_sudo = true; + } print_result(key, result); } + + if skipped_missing_sudo { + print_warning(t!( + "\nSome steps were skipped as sudo or equivalent could not be found." + )); + + #[cfg(unix)] + print_warning(t!( + "Install one of `sudo`, `doas`, `pkexec`, `run0` or `please` to run these steps." + )); + #[cfg(windows)] + print_warning(t!("Install gsudo or enable Windows Sudo to run these steps.")); + } } #[cfg(target_os = "linux")] diff --git a/src/runner.rs b/src/runner.rs index 53ea64a8..210212e9 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,18 +1,20 @@ use color_eyre::eyre::Result; +use rust_i18n::t; use std::borrow::Cow; use std::fmt::Debug; use tracing::debug; use crate::ctrlc; -use crate::error::{DryRun, SkipStep}; +use crate::error::{DryRun, MissingSudo, SkipStep}; use crate::execution_context::ExecutionContext; use crate::step::Step; -use crate::terminal::{print_error, should_retry}; +use crate::terminal::{print_error, print_warning, should_retry}; pub enum StepResult { Success, Failure, Ignored, + SkippedMissingSudo, Skipped(String), } @@ -21,7 +23,7 @@ impl StepResult { use StepResult::*; match self { - Success | Ignored | Skipped(_) => false, + Success | Ignored | Skipped(_) | SkippedMissingSudo => false, Failure => true, } } @@ -74,6 +76,11 @@ impl<'a> Runner<'a> { break; } Err(e) if e.downcast_ref::().is_some() => break, + Err(e) if e.downcast_ref::().is_some() => { + print_warning(t!("Skipping step, sudo is required")); + self.push_result(key, StepResult::SkippedMissingSudo); + break; + } Err(e) if e.downcast_ref::().is_some() => { if self.ctx.config().verbose() || self.ctx.config().show_skipped() { self.push_result(key, StepResult::Skipped(e.to_string())); diff --git a/src/terminal.rs b/src/terminal.rs index 6dbbf1dc..44d59bb8 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -173,6 +173,11 @@ impl Terminal { StepResult::Success => format!("{}", style(t!("OK")).bold().green()), StepResult::Failure => format!("{}", style(t!("FAILED")).bold().red()), StepResult::Ignored => format!("{}", style(t!("IGNORED")).bold().yellow()), + StepResult::SkippedMissingSudo => format!( + "{}: {}", + style(t!("SKIPPED")).bold().yellow(), + t!("Could not find sudo") + ), StepResult::Skipped(reason) => format!("{}: {}", style(t!("SKIPPED")).bold().blue(), reason), } ))