##// END OF EJS Templates
rhg: add exit code to HgError::Abort()...
Pulkit Goyal -
r48199:6e49769b default
parent child Browse files
Show More
@@ -0,0 +1,19 b''
1 pub type ExitCode = i32;
2
3 /// Successful exit
4 pub const OK: ExitCode = 0;
5
6 /// Generic abort
7 pub const ABORT: ExitCode = 255;
8
9 // Abort when there is a config related error
10 pub const CONFIG_ERROR_ABORT: ExitCode = 30;
11
12 // Abort when there is an error while parsing config
13 pub const CONFIG_PARSE_ERROR_ABORT: ExitCode = 10;
14
15 /// Generic something completed but did not succeed
16 pub const UNSUCCESSFUL: ExitCode = 1;
17
18 /// Command or feature not implemented by rhg
19 pub const UNIMPLEMENTED: ExitCode = 252;
@@ -8,6 +8,7 b''
8 // GNU General Public License version 2 or any later version.
8 // GNU General Public License version 2 or any later version.
9
9
10 use crate::errors::HgError;
10 use crate::errors::HgError;
11 use crate::exit_codes::CONFIG_PARSE_ERROR_ABORT;
11 use crate::utils::files::{get_bytes_from_path, get_path_from_bytes};
12 use crate::utils::files::{get_bytes_from_path, get_path_from_bytes};
12 use format_bytes::{format_bytes, write_bytes, DisplayBytes};
13 use format_bytes::{format_bytes, write_bytes, DisplayBytes};
13 use lazy_static::lazy_static;
14 use lazy_static::lazy_static;
@@ -73,11 +74,14 b' impl ConfigLayer {'
73 if let Some((section, item, value)) = parse_one(arg) {
74 if let Some((section, item, value)) = parse_one(arg) {
74 layer.add(section, item, value, None);
75 layer.add(section, item, value, None);
75 } else {
76 } else {
76 Err(HgError::abort(format!(
77 Err(HgError::abort(
77 "abort: malformed --config option: '{}' \
78 format!(
79 "abort: malformed --config option: '{}' \
78 (use --config section.name=value)",
80 (use --config section.name=value)",
79 String::from_utf8_lossy(arg),
81 String::from_utf8_lossy(arg),
80 )))?
82 ),
83 CONFIG_PARSE_ERROR_ABORT,
84 ))?
81 }
85 }
82 }
86 }
83 if layer.sections.is_empty() {
87 if layer.sections.is_empty() {
@@ -1,4 +1,5 b''
1 use crate::config::ConfigValueParseError;
1 use crate::config::ConfigValueParseError;
2 use crate::exit_codes;
2 use std::fmt;
3 use std::fmt;
3
4
4 /// Common error cases that can happen in many different APIs
5 /// Common error cases that can happen in many different APIs
@@ -27,9 +28,12 b' pub enum HgError {'
27
28
28 /// Operation cannot proceed for some other reason.
29 /// Operation cannot proceed for some other reason.
29 ///
30 ///
30 /// The given string is a short explanation for users, not intended to be
31 /// The message is a short explanation for users, not intended to be
31 /// machine-readable.
32 /// machine-readable.
32 Abort(String),
33 Abort {
34 message: String,
35 detailed_exit_code: exit_codes::ExitCode,
36 },
33
37
34 /// A configuration value is not in the expected syntax.
38 /// A configuration value is not in the expected syntax.
35 ///
39 ///
@@ -69,8 +73,15 b' impl HgError {'
69 pub fn unsupported(explanation: impl Into<String>) -> Self {
73 pub fn unsupported(explanation: impl Into<String>) -> Self {
70 HgError::UnsupportedFeature(explanation.into())
74 HgError::UnsupportedFeature(explanation.into())
71 }
75 }
72 pub fn abort(explanation: impl Into<String>) -> Self {
76
73 HgError::Abort(explanation.into())
77 pub fn abort(
78 explanation: impl Into<String>,
79 exit_code: exit_codes::ExitCode,
80 ) -> Self {
81 HgError::Abort {
82 message: explanation.into(),
83 detailed_exit_code: exit_code,
84 }
74 }
85 }
75 }
86 }
76
87
@@ -78,7 +89,7 b' impl HgError {'
78 impl fmt::Display for HgError {
89 impl fmt::Display for HgError {
79 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80 match self {
91 match self {
81 HgError::Abort(explanation) => write!(f, "{}", explanation),
92 HgError::Abort { message, .. } => write!(f, "{}", message),
82 HgError::IoError { error, context } => {
93 HgError::IoError { error, context } => {
83 write!(f, "abort: {}: {}", context, error)
94 write!(f, "abort: {}: {}", context, error)
84 }
95 }
@@ -11,6 +11,7 b' pub use ancestors::{AncestorsIterator, L'
11 pub mod dirstate;
11 pub mod dirstate;
12 pub mod dirstate_tree;
12 pub mod dirstate_tree;
13 pub mod discovery;
13 pub mod discovery;
14 pub mod exit_codes;
14 pub mod requirements;
15 pub mod requirements;
15 pub mod testing; // unconditionally built, for use from integration tests
16 pub mod testing; // unconditionally built, for use from integration tests
16 pub use dirstate::{
17 pub use dirstate::{
@@ -1,5 +1,6 b''
1 use crate::config::{Config, ConfigError, ConfigParseError};
1 use crate::config::{Config, ConfigError, ConfigParseError};
2 use crate::errors::{HgError, IoErrorContext, IoResultExt};
2 use crate::errors::{HgError, IoErrorContext, IoResultExt};
3 use crate::exit_codes;
3 use crate::requirements;
4 use crate::requirements;
4 use crate::utils::files::get_path_from_bytes;
5 use crate::utils::files::get_path_from_bytes;
5 use crate::utils::SliceExt;
6 use crate::utils::SliceExt;
@@ -150,6 +151,7 b' impl Repo {'
150 Some(b"abort") | None => HgError::abort(
151 Some(b"abort") | None => HgError::abort(
151 "abort: share source does not support share-safe requirement\n\
152 "abort: share source does not support share-safe requirement\n\
152 (see `hg help config.format.use-share-safe` for more information)",
153 (see `hg help config.format.use-share-safe` for more information)",
154 exit_codes::ABORT,
153 ),
155 ),
154 _ => HgError::unsupported("share-safe downgrade"),
156 _ => HgError::unsupported("share-safe downgrade"),
155 }
157 }
@@ -161,6 +163,7 b' impl Repo {'
161 "abort: version mismatch: source uses share-safe \
163 "abort: version mismatch: source uses share-safe \
162 functionality while the current share does not\n\
164 functionality while the current share does not\n\
163 (see `hg help config.format.use-share-safe` for more information)",
165 (see `hg help config.format.use-share-safe` for more information)",
166 exit_codes::ABORT,
164 ),
167 ),
165 _ => HgError::unsupported("share-safe upgrade"),
168 _ => HgError::unsupported("share-safe upgrade"),
166 }
169 }
@@ -1,10 +1,10 b''
1 use crate::exitcode;
2 use crate::ui::utf8_to_local;
1 use crate::ui::utf8_to_local;
3 use crate::ui::UiError;
2 use crate::ui::UiError;
4 use crate::NoRepoInCwdError;
3 use crate::NoRepoInCwdError;
5 use format_bytes::format_bytes;
4 use format_bytes::format_bytes;
6 use hg::config::{ConfigError, ConfigParseError, ConfigValueParseError};
5 use hg::config::{ConfigError, ConfigParseError, ConfigValueParseError};
7 use hg::errors::HgError;
6 use hg::errors::HgError;
7 use hg::exit_codes;
8 use hg::repo::RepoError;
8 use hg::repo::RepoError;
9 use hg::revlog::revlog::RevlogError;
9 use hg::revlog::revlog::RevlogError;
10 use hg::utils::files::get_bytes_from_path;
10 use hg::utils::files::get_bytes_from_path;
@@ -17,7 +17,7 b' pub enum CommandError {'
17 /// Exit with an error message and "standard" failure exit code.
17 /// Exit with an error message and "standard" failure exit code.
18 Abort {
18 Abort {
19 message: Vec<u8>,
19 message: Vec<u8>,
20 detailed_exit_code: exitcode::ExitCode,
20 detailed_exit_code: exit_codes::ExitCode,
21 },
21 },
22
22
23 /// Exit with a failure exit code but no message.
23 /// Exit with a failure exit code but no message.
@@ -32,12 +32,12 b' pub enum CommandError {'
32
32
33 impl CommandError {
33 impl CommandError {
34 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)
35 CommandError::abort_with_exit_code(message, exit_codes::ABORT)
36 }
36 }
37
37
38 pub fn abort_with_exit_code(
38 pub fn abort_with_exit_code(
39 message: impl AsRef<str>,
39 message: impl AsRef<str>,
40 detailed_exit_code: exitcode::ExitCode,
40 detailed_exit_code: exit_codes::ExitCode,
41 ) -> Self {
41 ) -> Self {
42 CommandError::Abort {
42 CommandError::Abort {
43 // TODO: bytes-based (instead of Unicode-based) formatting
43 // TODO: bytes-based (instead of Unicode-based) formatting
@@ -78,7 +78,7 b' impl From<ConfigValueParseError> for Com'
78 fn from(error: ConfigValueParseError) -> Self {
78 fn from(error: ConfigValueParseError) -> Self {
79 CommandError::abort_with_exit_code(
79 CommandError::abort_with_exit_code(
80 error.to_string(),
80 error.to_string(),
81 exitcode::CONFIG_ERROR_ABORT,
81 exit_codes::CONFIG_ERROR_ABORT,
82 )
82 )
83 }
83 }
84 }
84 }
@@ -100,7 +100,7 b' impl From<RepoError> for CommandError {'
100 b"abort: repository {} not found",
100 b"abort: repository {} not found",
101 get_bytes_from_path(at)
101 get_bytes_from_path(at)
102 ),
102 ),
103 detailed_exit_code: exitcode::ABORT,
103 detailed_exit_code: exit_codes::ABORT,
104 },
104 },
105 RepoError::ConfigParseError(error) => error.into(),
105 RepoError::ConfigParseError(error) => error.into(),
106 RepoError::Other(error) => error.into(),
106 RepoError::Other(error) => error.into(),
@@ -116,7 +116,7 b" impl<'a> From<&'a NoRepoInCwdError> for "
116 b"abort: no repository found in '{}' (.hg not found)!",
116 b"abort: no repository found in '{}' (.hg not found)!",
117 get_bytes_from_path(cwd)
117 get_bytes_from_path(cwd)
118 ),
118 ),
119 detailed_exit_code: exitcode::ABORT,
119 detailed_exit_code: exit_codes::ABORT,
120 }
120 }
121 }
121 }
122 }
122 }
@@ -149,7 +149,7 b' impl From<ConfigParseError> for CommandE'
149 line_message,
149 line_message,
150 message
150 message
151 ),
151 ),
152 detailed_exit_code: exitcode::CONFIG_ERROR_ABORT,
152 detailed_exit_code: exit_codes::CONFIG_ERROR_ABORT,
153 }
153 }
154 }
154 }
155 }
155 }
@@ -6,6 +6,7 b' use clap::Arg;'
6 use clap::ArgMatches;
6 use clap::ArgMatches;
7 use format_bytes::{format_bytes, join};
7 use format_bytes::{format_bytes, join};
8 use hg::config::{Config, ConfigSource};
8 use hg::config::{Config, ConfigSource};
9 use hg::exit_codes;
9 use hg::repo::{Repo, RepoError};
10 use hg::repo::{Repo, RepoError};
10 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
11 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
11 use hg::utils::SliceExt;
12 use hg::utils::SliceExt;
@@ -15,7 +16,6 b' use std::process::Command;'
15
16
16 mod blackbox;
17 mod blackbox;
17 mod error;
18 mod error;
18 mod exitcode;
19 mod ui;
19 mod ui;
20 use error::CommandError;
20 use error::CommandError;
21
21
@@ -297,7 +297,7 b' fn exit_code('
297 use_detailed_exit_code: bool,
297 use_detailed_exit_code: bool,
298 ) -> i32 {
298 ) -> i32 {
299 match result {
299 match result {
300 Ok(()) => exitcode::OK,
300 Ok(()) => exit_codes::OK,
301 Err(CommandError::Abort {
301 Err(CommandError::Abort {
302 message: _,
302 message: _,
303 detailed_exit_code,
303 detailed_exit_code,
@@ -305,15 +305,15 b' fn exit_code('
305 if use_detailed_exit_code {
305 if use_detailed_exit_code {
306 *detailed_exit_code
306 *detailed_exit_code
307 } else {
307 } else {
308 exitcode::ABORT
308 exit_codes::ABORT
309 }
309 }
310 }
310 }
311 Err(CommandError::Unsuccessful) => exitcode::UNSUCCESSFUL,
311 Err(CommandError::Unsuccessful) => exit_codes::UNSUCCESSFUL,
312
312
313 // Exit with a specific code and no error message to let a potential
313 // Exit with a specific code and no error message to let a potential
314 // wrapper script fallback to Python-based Mercurial.
314 // wrapper script fallback to Python-based Mercurial.
315 Err(CommandError::UnsupportedFeature { .. }) => {
315 Err(CommandError::UnsupportedFeature { .. }) => {
316 exitcode::UNIMPLEMENTED
316 exit_codes::UNIMPLEMENTED
317 }
317 }
318 }
318 }
319 }
319 }
@@ -352,7 +352,7 b' fn exit('
352 let result = command.status();
352 let result = command.status();
353 match result {
353 match result {
354 Ok(status) => std::process::exit(
354 Ok(status) => std::process::exit(
355 status.code().unwrap_or(exitcode::ABORT),
355 status.code().unwrap_or(exit_codes::ABORT),
356 ),
356 ),
357 Err(error) => {
357 Err(error) => {
358 let _ = ui.write_stderr(&format_bytes!(
358 let _ = ui.write_stderr(&format_bytes!(
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now