rust: add support for hints in error messages
authorRaphaël Gomès <rgomes@octobus.net>
Tue, 19 Jul 2022 17:07:09 +0200
changeset 49488 9f14126cfc4c
parent 49487 e8481625c582
child 49489 7c93e38a0bbd
rust: add support for hints in error messages This will be used by the narrow support code in the next commit.
rust/hg-core/src/config/layer.rs
rust/hg-core/src/errors.rs
rust/rhg/src/error.rs
rust/rhg/src/main.rs
--- 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 {