rust: add support for hints in error messages
This will be used by the narrow support code in the next commit.
--- a/rust/hg-core/src/config/layer.rs Mon Jul 11 11:59:13 2022 +0200
+++ b/rust/hg-core/src/config/layer.rs Tue Jul 19 17:07:09 2022 +0200
@@ -81,6 +81,7 @@
String::from_utf8_lossy(arg),
),
CONFIG_PARSE_ERROR_ABORT,
+ None,
))?
}
}
--- a/rust/hg-core/src/errors.rs Mon Jul 11 11:59:13 2022 +0200
+++ b/rust/hg-core/src/errors.rs Tue Jul 19 17:07:09 2022 +0200
@@ -33,6 +33,7 @@
Abort {
message: String,
detailed_exit_code: exit_codes::ExitCode,
+ hint: Option<String>,
},
/// A configuration value is not in the expected syntax.
@@ -82,10 +83,12 @@
pub fn abort(
explanation: impl Into<String>,
exit_code: exit_codes::ExitCode,
+ hint: Option<String>,
) -> Self {
HgError::Abort {
message: explanation.into(),
detailed_exit_code: exit_code,
+ hint,
}
}
}
--- a/rust/rhg/src/error.rs Mon Jul 11 11:59:13 2022 +0200
+++ b/rust/rhg/src/error.rs Tue Jul 19 17:07:09 2022 +0200
@@ -20,6 +20,7 @@
Abort {
message: Vec<u8>,
detailed_exit_code: exit_codes::ExitCode,
+ hint: Option<Vec<u8>>,
},
/// Exit with a failure exit code but no message.
@@ -50,6 +51,19 @@
// 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<str>,
+ detailed_exit_code: exit_codes::ExitCode,
+ hint: Option<impl AsRef<str>>,
+ ) -> 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 @@
CommandError::Abort {
message: message.as_ref().into(),
detailed_exit_code,
+ hint: None,
}
}
@@ -92,9 +107,12 @@
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<RepoError> 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<'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 @@
} 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,
+ )
}
}
--- a/rust/rhg/src/main.rs Mon Jul 11 11:59:13 2022 +0200
+++ b/rust/rhg/src/main.rs Tue Jul 19 17:07:09 2022 +0200
@@ -372,8 +372,7 @@
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 @@
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 {