Add output_changed_message!, replace some .expects (#1110)

This commit is contained in:
Gideon
2025-04-13 10:43:08 +02:00
committed by GitHub
parent 801dddacd4
commit fd406f0f82
4 changed files with 37 additions and 26 deletions

View File

@@ -20,12 +20,12 @@ use crate::execution_context::ExecutionContext;
use crate::executor::ExecutorOutput; use crate::executor::ExecutorOutput;
use crate::terminal::{print_separator, shell}; use crate::terminal::{print_separator, shell};
use crate::utils::{check_is_python_2_or_shim, get_require_sudo_string, require, require_option, which, PathExt}; use crate::utils::{check_is_python_2_or_shim, get_require_sudo_string, require, require_option, which, PathExt};
use crate::Step;
use crate::HOME_DIR; use crate::HOME_DIR;
use crate::{ use crate::{
error::{SkipStep, StepFailed, TopgradeError}, error::{SkipStep, StepFailed, TopgradeError},
terminal::print_warning, terminal::print_warning,
}; };
use crate::{output_changed_message, Step};
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub fn is_wsl() -> Result<bool> { pub fn is_wsl() -> Result<bool> {
@@ -472,8 +472,9 @@ fn run_vscode_compatible<const VSCODIUM: bool>(ctx: &ExecutionContext) -> Result
Version::parse(&item).map_err(std::convert::Into::into) Version::parse(&item).map_err(std::convert::Into::into)
} }
None => { None => {
return Err(eyre!(format!( return Err(eyre!(output_changed_message!(
"The output of `{bin_name} --version` changed, please file an issue to Topgrade: No first line" &format!("{bin_name} --version"),
"No first line"
))) )))
} }
}; };
@@ -481,9 +482,8 @@ fn run_vscode_compatible<const VSCODIUM: bool>(ctx: &ExecutionContext) -> Result
// Raise any errors in parsing the version // Raise any errors in parsing the version
// The benefit of handling VSCodium versions so old that the version format is something // The benefit of handling VSCodium versions so old that the version format is something
// unexpected is outweighed by the benefit of failing fast on new breaking versions // unexpected is outweighed by the benefit of failing fast on new breaking versions
let version = version.wrap_err(format!( let version =
"the output of `{bin_name} --version` changed, please file an issue to Topgrade" version.wrap_err_with(|| output_changed_message!(&format!("{bin_name} --version"), "Invalid version"))?;
))?;
debug!("Detected {name} version as: {version}"); debug!("Detected {name} version as: {version}");
if version < Version::new(1, 86, 0) { if version < Version::new(1, 86, 0) {
@@ -674,9 +674,12 @@ pub fn run_pip3_update(ctx: &ExecutionContext) -> Result<()> {
{ {
Ok(output) => { Ok(output) => {
let stdout = output.stdout.trim(); let stdout = output.stdout.trim();
stdout stdout.parse::<bool>().wrap_err_with(|| {
.parse::<bool>() output_changed_message!(
.expect("unexpected output that is not `true` or `false`") "pip config get global.break-system-packages",
"unexpected output that is not `true` or `false`"
)
})?
} }
// it can fail because this key may not be set // it can fail because this key may not be set
// //
@@ -1344,7 +1347,7 @@ pub fn run_uv(ctx: &ExecutionContext) -> Result<()> {
// 2. "0.5.11+1" // 2. "0.5.11+1"
}; };
let version = let version =
Version::parse(version_str).expect("the output of `uv --version` changed, please file an issue to Topgrade"); Version::parse(version_str).wrap_err_with(|| output_changed_message!("uv --version", "Invalid version"))?;
if version < Version::new(0, 4, 25) { if version < Version::new(0, 4, 25) {
// For uv before version 0.4.25 (exclusive), the `self` sub-command only // For uv before version 0.4.25 (exclusive), the `self` sub-command only

View File

@@ -3,7 +3,7 @@ use std::ffi::OsString;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use color_eyre::eyre; use color_eyre::eyre;
use color_eyre::eyre::Result; use color_eyre::eyre::{Context, Result};
use rust_i18n::t; use rust_i18n::t;
use walkdir::WalkDir; use walkdir::WalkDir;
@@ -12,7 +12,7 @@ use crate::error::TopgradeError;
use crate::execution_context::ExecutionContext; use crate::execution_context::ExecutionContext;
use crate::utils::require_option; use crate::utils::require_option;
use crate::utils::which; use crate::utils::which;
use crate::{config, Step}; use crate::{config, output_changed_message, Step};
fn get_execution_path() -> OsString { fn get_execution_path() -> OsString {
let mut path = OsString::from("/usr/bin:"); let mut path = OsString::from("/usr/bin:");
@@ -285,7 +285,8 @@ impl ArchPackageManager for Aura {
// Output will be something like: "aura x.x.x\n" // Output will be something like: "aura x.x.x\n"
let version_cmd_stdout = version_cmd_output.stdout; let version_cmd_stdout = version_cmd_output.stdout;
let version_str = version_cmd_stdout.trim_start_matches("aura ").trim_end(); let version_str = version_cmd_stdout.trim_start_matches("aura ").trim_end();
let version = Version::parse(version_str).expect("invalid version"); let version = Version::parse(version_str)
.wrap_err_with(|| output_changed_message!("aura --version", "invalid version"))?;
// Aura, since version 4.0.6, no longer needs sudo. // Aura, since version 4.0.6, no longer needs sudo.
// //

View File

@@ -7,7 +7,7 @@ use std::process::Command;
use std::{env::var, path::Path}; use std::{env::var, path::Path};
use crate::command::CommandExt; use crate::command::CommandExt;
use crate::{Step, HOME_DIR}; use crate::{output_changed_message, Step, HOME_DIR};
use color_eyre::eyre::eyre; use color_eyre::eyre::eyre;
use color_eyre::eyre::Context; use color_eyre::eyre::Context;
use color_eyre::eyre::Result; use color_eyre::eyre::Result;
@@ -470,16 +470,10 @@ pub fn run_nix(ctx: &ExecutionContext) -> Result<()> {
return Err(eyre!("`nix --version` output was empty")); return Err(eyre!("`nix --version` output was empty"));
} }
let captures = NIX_VERSION_REGEX.captures(get_version_cmd_first_line_stdout); let captures = NIX_VERSION_REGEX
let raw_version = match &captures { .captures(get_version_cmd_first_line_stdout)
None => { .ok_or_else(|| eyre!(output_changed_message!("nix --version", "regex did not match")))?;
return Err(eyre!( let raw_version = &captures[1];
"`nix --version` output was weird: {get_version_cmd_first_line_stdout:?}\n\
If the `nix --version` output format changed, please file an issue to Topgrade"
));
}
Some(captures) => &captures[1],
};
let version = let version =
Version::parse(raw_version).wrap_err_with(|| format!("Unable to parse Nix version: {raw_version:?}"))?; Version::parse(raw_version).wrap_err_with(|| format!("Unable to parse Nix version: {raw_version:?}"))?;
@@ -653,10 +647,11 @@ pub fn run_asdf(ctx: &ExecutionContext) -> Result<()> {
let mut remaining = version_stdout.trim_start_matches('v'); let mut remaining = version_stdout.trim_start_matches('v');
let idx = remaining let idx = remaining
.find('-') .find('-')
.expect("the output of `asdf version` changed, please file an issue to Topgrade"); .ok_or_else(|| eyre!(output_changed_message!("asdf version", "no dash (-) found")))?;
// remove the hash part // remove the hash part
remaining = &remaining[..idx]; remaining = &remaining[..idx];
let version = Version::parse(remaining).expect("should be a valid version"); let version =
Version::parse(remaining).wrap_err_with(|| output_changed_message!("asdf version", "invalid version"))?;
if version < Version::new(0, 15, 0) { if version < Version::new(0, 15, 0) {
ctx.run_type() ctx.run_type()
.execute(&asdf) .execute(&asdf)

View File

@@ -282,3 +282,15 @@ pub fn install_color_eyre() -> Result<()> {
.display_location_section(true) .display_location_section(true)
.install() .install()
} }
/// Macro to construct an error message for when the output of a command is unexpected.
#[macro_export]
macro_rules! output_changed_message {
($command:expr, $message:expr) => {
format!(
"The output of `{}` changed: {}. This is not your fault, this is an issue in Topgrade. Please open an issue at: https://github.com/topgrade-rs/topgrade/issues/new?template=bug_report.md",
$command,
$message,
)
};
}