##// END OF EJS Templates
rust: add support for hints in error messages...
Raphaël Gomès -
r50382:9f14126c default
parent child Browse files
Show More
@@ -81,6 +81,7 b' impl ConfigLayer {'
81 String::from_utf8_lossy(arg),
81 String::from_utf8_lossy(arg),
82 ),
82 ),
83 CONFIG_PARSE_ERROR_ABORT,
83 CONFIG_PARSE_ERROR_ABORT,
84 None,
84 ))?
85 ))?
85 }
86 }
86 }
87 }
@@ -33,6 +33,7 b' pub enum HgError {'
33 Abort {
33 Abort {
34 message: String,
34 message: String,
35 detailed_exit_code: exit_codes::ExitCode,
35 detailed_exit_code: exit_codes::ExitCode,
36 hint: Option<String>,
36 },
37 },
37
38
38 /// A configuration value is not in the expected syntax.
39 /// A configuration value is not in the expected syntax.
@@ -82,10 +83,12 b' impl HgError {'
82 pub fn abort(
83 pub fn abort(
83 explanation: impl Into<String>,
84 explanation: impl Into<String>,
84 exit_code: exit_codes::ExitCode,
85 exit_code: exit_codes::ExitCode,
86 hint: Option<String>,
85 ) -> Self {
87 ) -> Self {
86 HgError::Abort {
88 HgError::Abort {
87 message: explanation.into(),
89 message: explanation.into(),
88 detailed_exit_code: exit_code,
90 detailed_exit_code: exit_code,
91 hint,
89 }
92 }
90 }
93 }
91 }
94 }
@@ -20,6 +20,7 b' pub enum CommandError {'
20 Abort {
20 Abort {
21 message: Vec<u8>,
21 message: Vec<u8>,
22 detailed_exit_code: exit_codes::ExitCode,
22 detailed_exit_code: exit_codes::ExitCode,
23 hint: Option<Vec<u8>>,
23 },
24 },
24
25
25 /// Exit with a failure exit code but no message.
26 /// Exit with a failure exit code but no message.
@@ -50,6 +51,19 b' impl CommandError {'
50 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
51 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
51 message: utf8_to_local(message.as_ref()).into(),
52 message: utf8_to_local(message.as_ref()).into(),
52 detailed_exit_code: detailed_exit_code,
53 detailed_exit_code: detailed_exit_code,
54 hint: None,
55 }
56 }
57
58 pub fn abort_with_exit_code_and_hint(
59 message: impl AsRef<str>,
60 detailed_exit_code: exit_codes::ExitCode,
61 hint: Option<impl AsRef<str>>,
62 ) -> Self {
63 CommandError::Abort {
64 message: utf8_to_local(message.as_ref()).into(),
65 detailed_exit_code,
66 hint: hint.map(|h| utf8_to_local(h.as_ref()).into()),
53 }
67 }
54 }
68 }
55
69
@@ -62,6 +76,7 b' impl CommandError {'
62 CommandError::Abort {
76 CommandError::Abort {
63 message: message.as_ref().into(),
77 message: message.as_ref().into(),
64 detailed_exit_code,
78 detailed_exit_code,
79 hint: None,
65 }
80 }
66 }
81 }
67
82
@@ -92,9 +107,12 b' impl From<HgError> for CommandError {'
92 HgError::Abort {
107 HgError::Abort {
93 message,
108 message,
94 detailed_exit_code,
109 detailed_exit_code,
95 } => {
110 hint,
96 CommandError::abort_with_exit_code(message, detailed_exit_code)
111 } => CommandError::abort_with_exit_code_and_hint(
97 }
112 message,
113 detailed_exit_code,
114 hint,
115 ),
98 _ => CommandError::abort(error.to_string()),
116 _ => CommandError::abort(error.to_string()),
99 }
117 }
100 }
118 }
@@ -121,13 +139,15 b' impl From<UiError> for CommandError {'
121 impl From<RepoError> for CommandError {
139 impl From<RepoError> for CommandError {
122 fn from(error: RepoError) -> Self {
140 fn from(error: RepoError) -> Self {
123 match error {
141 match error {
124 RepoError::NotFound { at } => CommandError::Abort {
142 RepoError::NotFound { at } => {
125 message: format_bytes!(
143 CommandError::abort_with_exit_code_bytes(
126 b"abort: repository {} not found",
144 format_bytes!(
127 get_bytes_from_path(at)
145 b"abort: repository {} not found",
128 ),
146 get_bytes_from_path(at)
129 detailed_exit_code: exit_codes::ABORT,
147 ),
130 },
148 exit_codes::ABORT,
149 )
150 }
131 RepoError::ConfigParseError(error) => error.into(),
151 RepoError::ConfigParseError(error) => error.into(),
132 RepoError::Other(error) => error.into(),
152 RepoError::Other(error) => error.into(),
133 }
153 }
@@ -137,13 +157,13 b' impl From<RepoError> for CommandError {'
137 impl<'a> From<&'a NoRepoInCwdError> for CommandError {
157 impl<'a> From<&'a NoRepoInCwdError> for CommandError {
138 fn from(error: &'a NoRepoInCwdError) -> Self {
158 fn from(error: &'a NoRepoInCwdError) -> Self {
139 let NoRepoInCwdError { cwd } = error;
159 let NoRepoInCwdError { cwd } = error;
140 CommandError::Abort {
160 CommandError::abort_with_exit_code_bytes(
141 message: format_bytes!(
161 format_bytes!(
142 b"abort: no repository found in '{}' (.hg not found)!",
162 b"abort: no repository found in '{}' (.hg not found)!",
143 get_bytes_from_path(cwd)
163 get_bytes_from_path(cwd)
144 ),
164 ),
145 detailed_exit_code: exit_codes::ABORT,
165 exit_codes::ABORT,
146 }
166 )
147 }
167 }
148 }
168 }
149
169
@@ -168,15 +188,15 b' impl From<ConfigParseError> for CommandE'
168 } else {
188 } else {
169 Vec::new()
189 Vec::new()
170 };
190 };
171 CommandError::Abort {
191 CommandError::abort_with_exit_code_bytes(
172 message: format_bytes!(
192 format_bytes!(
173 b"config error at {}{}: {}",
193 b"config error at {}{}: {}",
174 origin,
194 origin,
175 line_message,
195 line_message,
176 message
196 message
177 ),
197 ),
178 detailed_exit_code: exit_codes::CONFIG_ERROR_ABORT,
198 exit_codes::CONFIG_ERROR_ABORT,
179 }
199 )
180 }
200 }
181 }
201 }
182
202
@@ -372,8 +372,7 b' fn exit_code('
372 match result {
372 match result {
373 Ok(()) => exit_codes::OK,
373 Ok(()) => exit_codes::OK,
374 Err(CommandError::Abort {
374 Err(CommandError::Abort {
375 message: _,
375 detailed_exit_code, ..
376 detailed_exit_code,
377 }) => {
376 }) => {
378 if use_detailed_exit_code {
377 if use_detailed_exit_code {
379 *detailed_exit_code
378 *detailed_exit_code
@@ -480,15 +479,15 b' fn exit_no_fallback('
480 match &result {
479 match &result {
481 Ok(_) => {}
480 Ok(_) => {}
482 Err(CommandError::Unsuccessful) => {}
481 Err(CommandError::Unsuccessful) => {}
483 Err(CommandError::Abort {
482 Err(CommandError::Abort { message, hint, .. }) => {
484 message,
483 // Ignore errors when writing to stderr, we’re already exiting
485 detailed_exit_code: _,
484 // with failure code so there’s not much more we can do.
486 }) => {
487 if !message.is_empty() {
485 if !message.is_empty() {
488 // Ignore errors when writing to stderr, we’re already exiting
489 // with failure code so there’s not much more we can do.
490 let _ = ui.write_stderr(&format_bytes!(b"{}\n", message));
486 let _ = ui.write_stderr(&format_bytes!(b"{}\n", message));
491 }
487 }
488 if let Some(hint) = hint {
489 let _ = ui.write_stderr(&format_bytes!(b"({})\n", hint));
490 }
492 }
491 }
493 Err(CommandError::UnsupportedFeature { message }) => {
492 Err(CommandError::UnsupportedFeature { message }) => {
494 match on_unsupported {
493 match on_unsupported {
General Comments 0
You need to be logged in to leave comments. Login now