##// 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 use crate::ui::utf8_to_local;
2 use crate::ui::utf8_to_local;
2 use crate::ui::UiError;
3 use crate::ui::UiError;
3 use crate::NoRepoInCwdError;
4 use crate::NoRepoInCwdError;
@@ -14,7 +15,10 b' use std::convert::From;'
14 #[derive(Debug)]
15 #[derive(Debug)]
15 pub enum CommandError {
16 pub enum CommandError {
16 /// Exit with an error message and "standard" failure exit code.
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 /// Exit with a failure exit code but no message.
23 /// Exit with a failure exit code but no message.
20 Unsuccessful,
24 Unsuccessful,
@@ -28,11 +32,19 b' pub enum CommandError {'
28
32
29 impl CommandError {
33 impl CommandError {
30 pub fn abort(message: impl AsRef<str>) -> Self {
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 CommandError::Abort {
42 CommandError::Abort {
32 // TODO: bytes-based (instead of Unicode-based) formatting
43 // TODO: bytes-based (instead of Unicode-based) formatting
33 // of error messages to handle non-UTF-8 filenames etc:
44 // of error messages to handle non-UTF-8 filenames etc:
34 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
45 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
35 message: utf8_to_local(message.as_ref()).into(),
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 impl From<ConfigValueParseError> for CommandError {
77 impl From<ConfigValueParseError> for CommandError {
66 fn from(error: ConfigValueParseError) -> Self {
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 b"abort: repository {} not found",
100 b"abort: repository {} not found",
86 get_bytes_from_path(at)
101 get_bytes_from_path(at)
87 ),
102 ),
103 detailed_exit_code: exitcode::ABORT,
88 },
104 },
89 RepoError::ConfigParseError(error) => error.into(),
105 RepoError::ConfigParseError(error) => error.into(),
90 RepoError::Other(error) => error.into(),
106 RepoError::Other(error) => error.into(),
@@ -100,6 +116,7 b" impl<'a> From<&'a NoRepoInCwdError> for "
100 b"abort: no repository found in '{}' (.hg not found)!",
116 b"abort: no repository found in '{}' (.hg not found)!",
101 get_bytes_from_path(cwd)
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 line_message,
149 line_message,
133 message
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 /// Generic abort
6 /// Generic abort
7 pub const ABORT: ExitCode = 255;
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 /// Generic something completed but did not succeed
12 /// Generic something completed but did not succeed
10 pub const UNSUCCESSFUL: ExitCode = 1;
13 pub const UNSUCCESSFUL: ExitCode = 1;
11
14
@@ -82,7 +82,14 b' fn main_with_result('
82 let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?;
82 let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?;
83 blackbox.log_command_start();
83 blackbox.log_command_start();
84 let result = run(&invocation);
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 result
93 result
87 }
94 }
88
95
@@ -114,6 +121,7 b' fn main() {'
114 error,
121 error,
115 cwd.display()
122 cwd.display()
116 ))),
123 ))),
124 false,
117 )
125 )
118 })
126 })
119 });
127 });
@@ -125,7 +133,13 b' fn main() {'
125 // "unsupported" error but that is not enforced by the type system.
133 // "unsupported" error but that is not enforced by the type system.
126 let on_unsupported = OnUnsupported::Abort;
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 if let Some(repo_path_bytes) = &early_args.repo {
145 if let Some(repo_path_bytes) = &early_args.repo {
@@ -145,6 +159,11 b' fn main() {'
145 repo_path_bytes
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 &ui,
179 &ui,
161 OnUnsupported::from_config(&ui, &non_repo_config),
180 OnUnsupported::from_config(&ui, &non_repo_config),
162 Err(error.into()),
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 repo_result.as_ref(),
200 repo_result.as_ref(),
177 config,
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 match result {
220 match result {
184 Ok(()) => exitcode::OK,
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 Err(CommandError::Unsuccessful) => exitcode::UNSUCCESSFUL,
232 Err(CommandError::Unsuccessful) => exitcode::UNSUCCESSFUL,
187
233
188 // Exit with a specific code and no error message to let a potential
234 // Exit with a specific code and no error message to let a potential
@@ -198,6 +244,7 b' fn exit('
198 ui: &Ui,
244 ui: &Ui,
199 mut on_unsupported: OnUnsupported,
245 mut on_unsupported: OnUnsupported,
200 result: Result<(), CommandError>,
246 result: Result<(), CommandError>,
247 use_detailed_exit_code: bool,
201 ) -> ! {
248 ) -> ! {
202 if let (
249 if let (
203 OnUnsupported::Fallback { executable },
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 fn exit_no_fallback(
291 fn exit_no_fallback(
245 ui: &Ui,
292 ui: &Ui,
246 on_unsupported: OnUnsupported,
293 on_unsupported: OnUnsupported,
247 result: Result<(), CommandError>,
294 result: Result<(), CommandError>,
295 use_detailed_exit_code: bool,
248 ) -> ! {
296 ) -> ! {
249 match &result {
297 match &result {
250 Ok(_) => {}
298 Ok(_) => {}
251 Err(CommandError::Unsuccessful) => {}
299 Err(CommandError::Unsuccessful) => {}
252 Err(CommandError::Abort { message }) => {
300 Err(CommandError::Abort {
301 message,
302 detailed_exit_code: _,
303 }) => {
253 if !message.is_empty() {
304 if !message.is_empty() {
254 // Ignore errors when writing to stderr, we’re already exiting
305 // Ignore errors when writing to stderr, we’re already exiting
255 // with failure code so there’s not much more we can do.
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 macro_rules! subcommands {
326 macro_rules! subcommands {
@@ -411,6 +462,7 b' impl OnUnsupported {'
411 "abort: 'rhg.on-unsupported=fallback' without \
462 "abort: 'rhg.on-unsupported=fallback' without \
412 'rhg.fallback-executable' set."
463 'rhg.fallback-executable' set."
413 )),
464 )),
465 false,
414 )
466 )
415 })
467 })
416 .to_owned(),
468 .to_owned(),
@@ -3,8 +3,6 b' hide outer repo'
3
3
4 Invalid syntax: no value
4 Invalid syntax: no value
5
5
6 TODO: add rhg support for detailed exit codes
7 #if no-rhg
8 $ cat > .hg/hgrc << EOF
6 $ cat > .hg/hgrc << EOF
9 > novaluekey
7 > novaluekey
10 > EOF
8 > EOF
@@ -37,7 +35,6 b' Test hint about invalid syntax from lead'
37 $ hg showconfig
35 $ hg showconfig
38 config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section]
36 config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section]
39 [30]
37 [30]
40 #endif
41
38
42 Reset hgrc
39 Reset hgrc
43
40
@@ -90,12 +90,9 b" However, we can't prevent it from loadin"
90
90
91 $ mkdir -p badrepo/.hg
91 $ mkdir -p badrepo/.hg
92 $ echo 'invalid-syntax' > badrepo/.hg/hgrc
92 $ echo 'invalid-syntax' > badrepo/.hg/hgrc
93 TODO: add rhg support for detailed exit codes
94 #if no-rhg
95 $ hg log -b -Rbadrepo default
93 $ hg log -b -Rbadrepo default
96 config error at badrepo/.hg/hgrc:1: invalid-syntax
94 config error at badrepo/.hg/hgrc:1: invalid-syntax
97 [30]
95 [30]
98 #endif
99
96
100 $ hg log -b --cwd=inexistent default
97 $ hg log -b --cwd=inexistent default
101 abort: $ENOENT$: 'inexistent'
98 abort: $ENOENT$: 'inexistent'
General Comments 0
You need to be logged in to leave comments. Login now