# HG changeset patch # User Raphaël Gomès # Date 2022-07-19 15:07:09 # Node ID 9f14126cfc4cae50e74056731bc84eab4a913925 # Parent e8481625c582323cea98b0272e5724decb4b68ba rust: add support for hints in error messages This will be used by the narrow support code in the next commit. diff --git a/rust/hg-core/src/config/layer.rs b/rust/hg-core/src/config/layer.rs --- a/rust/hg-core/src/config/layer.rs +++ b/rust/hg-core/src/config/layer.rs @@ -81,6 +81,7 @@ impl ConfigLayer { String::from_utf8_lossy(arg), ), CONFIG_PARSE_ERROR_ABORT, + None, ))? } } diff --git a/rust/hg-core/src/errors.rs b/rust/hg-core/src/errors.rs --- a/rust/hg-core/src/errors.rs +++ b/rust/hg-core/src/errors.rs @@ -33,6 +33,7 @@ pub enum HgError { Abort { message: String, detailed_exit_code: exit_codes::ExitCode, + hint: Option, }, /// A configuration value is not in the expected syntax. @@ -82,10 +83,12 @@ impl HgError { pub fn abort( explanation: impl Into, exit_code: exit_codes::ExitCode, + hint: Option, ) -> Self { HgError::Abort { message: explanation.into(), detailed_exit_code: exit_code, + hint, } } } diff --git a/rust/rhg/src/error.rs b/rust/rhg/src/error.rs --- a/rust/rhg/src/error.rs +++ b/rust/rhg/src/error.rs @@ -20,6 +20,7 @@ pub enum CommandError { Abort { message: Vec, detailed_exit_code: exit_codes::ExitCode, + hint: Option>, }, /// Exit with a failure exit code but no message. @@ -50,6 +51,19 @@ impl CommandError { // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output message: utf8_to_local(message.as_ref()).into(), detailed_exit_code: detailed_exit_code, + hint: None, + } + } + + pub fn abort_with_exit_code_and_hint( + message: impl AsRef, + detailed_exit_code: exit_codes::ExitCode, + hint: Option>, + ) -> Self { + CommandError::Abort { + message: utf8_to_local(message.as_ref()).into(), + detailed_exit_code, + hint: hint.map(|h| utf8_to_local(h.as_ref()).into()), } } @@ -62,6 +76,7 @@ impl CommandError { CommandError::Abort { message: message.as_ref().into(), detailed_exit_code, + hint: None, } } @@ -92,9 +107,12 @@ impl From for CommandError { HgError::Abort { message, detailed_exit_code, - } => { - CommandError::abort_with_exit_code(message, detailed_exit_code) - } + hint, + } => CommandError::abort_with_exit_code_and_hint( + message, + detailed_exit_code, + hint, + ), _ => CommandError::abort(error.to_string()), } } @@ -121,13 +139,15 @@ impl From for CommandError { impl From for CommandError { fn from(error: RepoError) -> Self { match error { - RepoError::NotFound { at } => CommandError::Abort { - message: format_bytes!( - b"abort: repository {} not found", - get_bytes_from_path(at) - ), - detailed_exit_code: exit_codes::ABORT, - }, + RepoError::NotFound { at } => { + CommandError::abort_with_exit_code_bytes( + format_bytes!( + b"abort: repository {} not found", + get_bytes_from_path(at) + ), + exit_codes::ABORT, + ) + } RepoError::ConfigParseError(error) => error.into(), RepoError::Other(error) => error.into(), } @@ -137,13 +157,13 @@ impl From for CommandError { impl<'a> From<&'a NoRepoInCwdError> for CommandError { fn from(error: &'a NoRepoInCwdError) -> Self { let NoRepoInCwdError { cwd } = error; - CommandError::Abort { - message: format_bytes!( + CommandError::abort_with_exit_code_bytes( + format_bytes!( b"abort: no repository found in '{}' (.hg not found)!", get_bytes_from_path(cwd) ), - detailed_exit_code: exit_codes::ABORT, - } + exit_codes::ABORT, + ) } } @@ -168,15 +188,15 @@ impl From for CommandE } else { Vec::new() }; - CommandError::Abort { - message: format_bytes!( + CommandError::abort_with_exit_code_bytes( + format_bytes!( b"config error at {}{}: {}", origin, line_message, message ), - detailed_exit_code: exit_codes::CONFIG_ERROR_ABORT, - } + exit_codes::CONFIG_ERROR_ABORT, + ) } } diff --git a/rust/rhg/src/main.rs b/rust/rhg/src/main.rs --- a/rust/rhg/src/main.rs +++ b/rust/rhg/src/main.rs @@ -372,8 +372,7 @@ fn exit_code( match result { Ok(()) => exit_codes::OK, Err(CommandError::Abort { - message: _, - detailed_exit_code, + detailed_exit_code, .. }) => { if use_detailed_exit_code { *detailed_exit_code @@ -480,15 +479,15 @@ fn exit_no_fallback( match &result { Ok(_) => {} Err(CommandError::Unsuccessful) => {} - Err(CommandError::Abort { - message, - detailed_exit_code: _, - }) => { + Err(CommandError::Abort { message, hint, .. }) => { + // Ignore errors when writing to stderr, we’re already exiting + // with failure code so there’s not much more we can do. if !message.is_empty() { - // Ignore errors when writing to stderr, we’re already exiting - // with failure code so there’s not much more we can do. let _ = ui.write_stderr(&format_bytes!(b"{}\n", message)); } + if let Some(hint) = hint { + let _ = ui.write_stderr(&format_bytes!(b"({})\n", hint)); + } } Err(CommandError::UnsupportedFeature { message }) => { match on_unsupported {