##// END OF EJS Templates
rhg: add support for detailed exit code for ConfigParseError...
Pulkit Goyal -
r47576:821929d5 default
parent child Browse files
Show More
@@ -1,3 +1,4 b''
1 use crate::exitcode;
1 2 use crate::ui::utf8_to_local;
2 3 use crate::ui::UiError;
3 4 use crate::NoRepoInCwdError;
@@ -14,7 +15,10 b' use std::convert::From;'
14 15 #[derive(Debug)]
15 16 pub enum CommandError {
16 17 /// Exit with an error message and "standard" failure exit code.
17 Abort { message: Vec<u8> },
18 Abort {
19 message: Vec<u8>,
20 detailed_exit_code: exitcode::ExitCode,
21 },
18 22
19 23 /// Exit with a failure exit code but no message.
20 24 Unsuccessful,
@@ -28,11 +32,19 b' pub enum CommandError {'
28 32
29 33 impl CommandError {
30 34 pub fn abort(message: impl AsRef<str>) -> Self {
35 CommandError::abort_with_exit_code(message, exitcode::ABORT)
36 }
37
38 pub fn abort_with_exit_code(
39 message: impl AsRef<str>,
40 detailed_exit_code: exitcode::ExitCode,
41 ) -> Self {
31 42 CommandError::Abort {
32 43 // TODO: bytes-based (instead of Unicode-based) formatting
33 44 // of error messages to handle non-UTF-8 filenames etc:
34 45 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
35 46 message: utf8_to_local(message.as_ref()).into(),
47 detailed_exit_code: detailed_exit_code,
36 48 }
37 49 }
38 50
@@ -64,7 +76,10 b' impl From<HgError> for CommandError {'
64 76
65 77 impl From<ConfigValueParseError> for CommandError {
66 78 fn from(error: ConfigValueParseError) -> Self {
67 CommandError::abort(error.to_string())
79 CommandError::abort_with_exit_code(
80 error.to_string(),
81 exitcode::CONFIG_ERROR_ABORT,
82 )
68 83 }
69 84 }
70 85
@@ -85,6 +100,7 b' impl From<RepoError> for CommandError {'
85 100 b"abort: repository {} not found",
86 101 get_bytes_from_path(at)
87 102 ),
103 detailed_exit_code: exitcode::ABORT,
88 104 },
89 105 RepoError::ConfigParseError(error) => error.into(),
90 106 RepoError::Other(error) => error.into(),
@@ -100,6 +116,7 b" impl<'a> From<&'a NoRepoInCwdError> for "
100 116 b"abort: no repository found in '{}' (.hg not found)!",
101 117 get_bytes_from_path(cwd)
102 118 ),
119 detailed_exit_code: exitcode::ABORT,
103 120 }
104 121 }
105 122 }
@@ -132,6 +149,7 b' impl From<ConfigParseError> for CommandE'
132 149 line_message,
133 150 message
134 151 ),
152 detailed_exit_code: exitcode::CONFIG_ERROR_ABORT,
135 153 }
136 154 }
137 155 }
@@ -6,6 +6,9 b' pub const OK: ExitCode = 0;'
6 6 /// Generic abort
7 7 pub const ABORT: ExitCode = 255;
8 8
9 // Abort when there is a config related error
10 pub const CONFIG_ERROR_ABORT: ExitCode = 30;
11
9 12 /// Generic something completed but did not succeed
10 13 pub const UNSUCCESSFUL: ExitCode = 1;
11 14
@@ -82,7 +82,14 b' fn main_with_result('
82 82 let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?;
83 83 blackbox.log_command_start();
84 84 let result = run(&invocation);
85 blackbox.log_command_end(exit_code(&result));
85 blackbox.log_command_end(exit_code(
86 &result,
87 // TODO: show a warning or combine with original error if `get_bool`
88 // returns an error
89 config
90 .get_bool(b"ui", b"detailed-exit-code")
91 .unwrap_or(false),
92 ));
86 93 result
87 94 }
88 95
@@ -114,6 +121,7 b' fn main() {'
114 121 error,
115 122 cwd.display()
116 123 ))),
124 false,
117 125 )
118 126 })
119 127 });
@@ -125,7 +133,13 b' fn main() {'
125 133 // "unsupported" error but that is not enforced by the type system.
126 134 let on_unsupported = OnUnsupported::Abort;
127 135
128 exit(&initial_current_dir, &ui, on_unsupported, Err(error.into()))
136 exit(
137 &initial_current_dir,
138 &ui,
139 on_unsupported,
140 Err(error.into()),
141 false,
142 )
129 143 });
130 144
131 145 if let Some(repo_path_bytes) = &early_args.repo {
@@ -145,6 +159,11 b' fn main() {'
145 159 repo_path_bytes
146 160 ),
147 161 }),
162 // TODO: show a warning or combine with original error if
163 // `get_bool` returns an error
164 non_repo_config
165 .get_bool(b"ui", b"detailed-exit-code")
166 .unwrap_or(false),
148 167 )
149 168 }
150 169 }
@@ -160,6 +179,11 b' fn main() {'
160 179 &ui,
161 180 OnUnsupported::from_config(&ui, &non_repo_config),
162 181 Err(error.into()),
182 // TODO: show a warning or combine with original error if
183 // `get_bool` returns an error
184 non_repo_config
185 .get_bool(b"ui", b"detailed-exit-code")
186 .unwrap_or(false),
163 187 ),
164 188 };
165 189
@@ -176,13 +200,35 b' fn main() {'
176 200 repo_result.as_ref(),
177 201 config,
178 202 );
179 exit(&initial_current_dir, &ui, on_unsupported, result)
203 exit(
204 &initial_current_dir,
205 &ui,
206 on_unsupported,
207 result,
208 // TODO: show a warning or combine with original error if `get_bool`
209 // returns an error
210 config
211 .get_bool(b"ui", b"detailed-exit-code")
212 .unwrap_or(false),
213 )
180 214 }
181 215
182 fn exit_code(result: &Result<(), CommandError>) -> i32 {
216 fn exit_code(
217 result: &Result<(), CommandError>,
218 use_detailed_exit_code: bool,
219 ) -> i32 {
183 220 match result {
184 221 Ok(()) => exitcode::OK,
185 Err(CommandError::Abort { .. }) => exitcode::ABORT,
222 Err(CommandError::Abort {
223 message: _,
224 detailed_exit_code,
225 }) => {
226 if use_detailed_exit_code {
227 *detailed_exit_code
228 } else {
229 exitcode::ABORT
230 }
231 }
186 232 Err(CommandError::Unsuccessful) => exitcode::UNSUCCESSFUL,
187 233
188 234 // Exit with a specific code and no error message to let a potential
@@ -198,6 +244,7 b' fn exit('
198 244 ui: &Ui,
199 245 mut on_unsupported: OnUnsupported,
200 246 result: Result<(), CommandError>,
247 use_detailed_exit_code: bool,
201 248 ) -> ! {
202 249 if let (
203 250 OnUnsupported::Fallback { executable },
@@ -238,18 +285,22 b' fn exit('
238 285 }
239 286 }
240 287 }
241 exit_no_fallback(ui, on_unsupported, result)
288 exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code)
242 289 }
243 290
244 291 fn exit_no_fallback(
245 292 ui: &Ui,
246 293 on_unsupported: OnUnsupported,
247 294 result: Result<(), CommandError>,
295 use_detailed_exit_code: bool,
248 296 ) -> ! {
249 297 match &result {
250 298 Ok(_) => {}
251 299 Err(CommandError::Unsuccessful) => {}
252 Err(CommandError::Abort { message }) => {
300 Err(CommandError::Abort {
301 message,
302 detailed_exit_code: _,
303 }) => {
253 304 if !message.is_empty() {
254 305 // Ignore errors when writing to stderr, we’re already exiting
255 306 // with failure code so there’s not much more we can do.
@@ -269,7 +320,7 b' fn exit_no_fallback('
269 320 }
270 321 }
271 322 }
272 std::process::exit(exit_code(&result))
323 std::process::exit(exit_code(&result, use_detailed_exit_code))
273 324 }
274 325
275 326 macro_rules! subcommands {
@@ -411,6 +462,7 b' impl OnUnsupported {'
411 462 "abort: 'rhg.on-unsupported=fallback' without \
412 463 'rhg.fallback-executable' set."
413 464 )),
465 false,
414 466 )
415 467 })
416 468 .to_owned(),
@@ -3,8 +3,6 b' hide outer repo'
3 3
4 4 Invalid syntax: no value
5 5
6 TODO: add rhg support for detailed exit codes
7 #if no-rhg
8 6 $ cat > .hg/hgrc << EOF
9 7 > novaluekey
10 8 > EOF
@@ -37,7 +35,6 b' Test hint about invalid syntax from lead'
37 35 $ hg showconfig
38 36 config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section]
39 37 [30]
40 #endif
41 38
42 39 Reset hgrc
43 40
@@ -90,12 +90,9 b" However, we can't prevent it from loadin"
90 90
91 91 $ mkdir -p badrepo/.hg
92 92 $ echo 'invalid-syntax' > badrepo/.hg/hgrc
93 TODO: add rhg support for detailed exit codes
94 #if no-rhg
95 93 $ hg log -b -Rbadrepo default
96 94 config error at badrepo/.hg/hgrc:1: invalid-syntax
97 95 [30]
98 #endif
99 96
100 97 $ hg log -b --cwd=inexistent default
101 98 abort: $ENOENT$: 'inexistent'
General Comments 0
You need to be logged in to leave comments. Login now