From c5f2d7b47362daab4a3e00f9a03cbd594a0b4f78 Mon Sep 17 00:00:00 2001 From: Samuel Grahn Date: Thu, 12 Dec 2024 02:19:03 +0100 Subject: [PATCH] Detect Elan self update disabled (e.g. installed from distro repos) (#998) * Add config option for Elan self-update * Format & Config * Revert "Format & Config" This reverts commit 9eedecce8b312f8ad60563488c98cccfd50c0173. * Revert "Add config option for Elan self-update" This reverts commit 8c80c7a7d63ecd0936e0bd5cb07c2cbb1452c1fd. * Allow self-update to fail when disabled * Formatting * Don't print in case of failed self-update * Formatting * Use the code suggested :) * Follow the recommendations by Clippy --- src/steps/generic.rs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/steps/generic.rs b/src/steps/generic.rs index 18dd92f4..760845be 100644 --- a/src/steps/generic.rs +++ b/src/steps/generic.rs @@ -258,10 +258,35 @@ pub fn run_elan(ctx: &ExecutionContext) -> Result<()> { let elan = require("elan")?; print_separator("elan"); - ctx.run_type() - .execute(&elan) - .args(["self", "update"]) - .status_checked()?; + + let disabled_error_msg = "self-update is disabled"; + let executor_output = ctx.run_type().execute(&elan).args(["self", "update"]).output()?; + match executor_output { + ExecutorOutput::Wet(command_output) => { + if command_output.status.success() { + // Flush the captured output + std::io::stdout().lock().write_all(&command_output.stdout).unwrap(); + std::io::stderr().lock().write_all(&command_output.stderr).unwrap(); + } else { + let stderr_as_str = std::str::from_utf8(&command_output.stderr).unwrap(); + if stderr_as_str.contains(disabled_error_msg) { + // `elan` is externally managed, we cannot do the update. Users + // won't see any error message because Topgrade captures them + // all. + } else { + // `elan` is NOT externally managed, `elan self update` can + // be performed, but the invocation failed, so we report the + // error to the user and error out. + std::io::stdout().lock().write_all(&command_output.stdout).unwrap(); + std::io::stderr().lock().write_all(&command_output.stderr).unwrap(); + + return Err(StepFailed.into()); + } + } + } + ExecutorOutput::Dry => { /* nothing needed because in a dry run */ } + } + ctx.run_type().execute(&elan).arg("update").status_checked() }