D10253: rhg: add support for detailed exit code for ConfigParseError
pulkit (Pulkit Goyal)
phabricator at mercurial-scm.org
Tue Mar 23 20:39:50 UTC 2021
pulkit created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.
REVISION SUMMARY
This patch adds basic support for detailed exit code to rhg with support for
ConfigParseError.
For now, if parsing the config results in error, we silently fallbacks to
`false`. The python version in this case emits a traceback.
REPOSITORY
rHG Mercurial
BRANCH
default
REVISION DETAIL
https://phab.mercurial-scm.org/D10253
AFFECTED FILES
rust/rhg/src/error.rs
rust/rhg/src/exitcode.rs
rust/rhg/src/main.rs
tests/test-config.t
tests/test-dispatch.t
CHANGE DETAILS
diff --git a/tests/test-dispatch.t b/tests/test-dispatch.t
--- a/tests/test-dispatch.t
+++ b/tests/test-dispatch.t
@@ -90,12 +90,9 @@
$ mkdir -p badrepo/.hg
$ echo 'invalid-syntax' > badrepo/.hg/hgrc
-TODO: add rhg support for detailed exit codes
-#if no-rhg
$ hg log -b -Rbadrepo default
config error at badrepo/.hg/hgrc:1: invalid-syntax
[30]
-#endif
$ hg log -b --cwd=inexistent default
abort: $ENOENT$: 'inexistent'
diff --git a/tests/test-config.t b/tests/test-config.t
--- a/tests/test-config.t
+++ b/tests/test-config.t
@@ -3,8 +3,6 @@
Invalid syntax: no value
-TODO: add rhg support for detailed exit codes
-#if no-rhg
$ cat > .hg/hgrc << EOF
> novaluekey
> EOF
@@ -37,7 +35,6 @@
$ hg showconfig
config error at $TESTTMP/.hg/hgrc:1: unexpected leading whitespace: [section]
[30]
-#endif
Reset hgrc
diff --git a/rust/rhg/src/main.rs b/rust/rhg/src/main.rs
--- a/rust/rhg/src/main.rs
+++ b/rust/rhg/src/main.rs
@@ -82,7 +82,14 @@
let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?;
blackbox.log_command_start();
let result = run(&invocation);
- blackbox.log_command_end(exit_code(&result));
+ blackbox.log_command_end(exit_code(
+ &result,
+ // TODO: show a warning or combine with original error if `get_bool`
+ // returns an error
+ config
+ .get_bool(b"ui", b"detailed-exit-code")
+ .unwrap_or(false),
+ ));
result
}
@@ -114,6 +121,7 @@
error,
cwd.display()
))),
+ false,
)
})
});
@@ -125,7 +133,13 @@
// "unsupported" error but that is not enforced by the type system.
let on_unsupported = OnUnsupported::Abort;
- exit(&initial_current_dir, &ui, on_unsupported, Err(error.into()))
+ exit(
+ &initial_current_dir,
+ &ui,
+ on_unsupported,
+ Err(error.into()),
+ false,
+ )
});
if let Some(repo_path_bytes) = &early_args.repo {
@@ -145,6 +159,11 @@
repo_path_bytes
),
}),
+ // TODO: show a warning or combine with original error if `get_bool`
+ // returns an error
+ non_repo_config
+ .get_bool(b"ui", b"detailed-exit-code")
+ .unwrap_or(false),
)
}
}
@@ -160,6 +179,11 @@
&ui,
OnUnsupported::from_config(&ui, &non_repo_config),
Err(error.into()),
+ // TODO: show a warning or combine with original error if `get_bool`
+ // returns an error
+ non_repo_config
+ .get_bool(b"ui", b"detailed-exit-code")
+ .unwrap_or(false),
),
};
@@ -176,13 +200,35 @@
repo_result.as_ref(),
config,
);
- exit(&initial_current_dir, &ui, on_unsupported, result)
+ exit(
+ &initial_current_dir,
+ &ui,
+ on_unsupported,
+ result,
+ // TODO: show a warning or combine with original error if `get_bool`
+ // returns an error
+ config
+ .get_bool(b"ui", b"detailed-exit-code")
+ .unwrap_or(false),
+ )
}
-fn exit_code(result: &Result<(), CommandError>) -> i32 {
+fn exit_code(
+ result: &Result<(), CommandError>,
+ use_detailed_exit_code: bool,
+) -> i32 {
match result {
Ok(()) => exitcode::OK,
- Err(CommandError::Abort { .. }) => exitcode::ABORT,
+ Err(CommandError::Abort {
+ message: _,
+ detailed_exit_code,
+ }) => {
+ if use_detailed_exit_code {
+ *detailed_exit_code
+ } else {
+ exitcode::ABORT
+ }
+ }
Err(CommandError::Unsuccessful) => exitcode::UNSUCCESSFUL,
// Exit with a specific code and no error message to let a potential
@@ -198,6 +244,7 @@
ui: &Ui,
mut on_unsupported: OnUnsupported,
result: Result<(), CommandError>,
+ use_detailed_exit_code: bool,
) -> ! {
if let (
OnUnsupported::Fallback { executable },
@@ -238,18 +285,22 @@
}
}
}
- exit_no_fallback(ui, on_unsupported, result)
+ exit_no_fallback(ui, on_unsupported, result, use_detailed_exit_code)
}
fn exit_no_fallback(
ui: &Ui,
on_unsupported: OnUnsupported,
result: Result<(), CommandError>,
+ use_detailed_exit_code: bool,
) -> ! {
match &result {
Ok(_) => {}
Err(CommandError::Unsuccessful) => {}
- Err(CommandError::Abort { message }) => {
+ Err(CommandError::Abort {
+ message,
+ detailed_exit_code: _,
+ }) => {
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.
@@ -269,7 +320,7 @@
}
}
}
- std::process::exit(exit_code(&result))
+ std::process::exit(exit_code(&result, use_detailed_exit_code))
}
macro_rules! subcommands {
@@ -411,6 +462,7 @@
"abort: 'rhg.on-unsupported=fallback' without \
'rhg.fallback-executable' set."
)),
+ false,
)
})
.to_owned(),
diff --git a/rust/rhg/src/exitcode.rs b/rust/rhg/src/exitcode.rs
--- a/rust/rhg/src/exitcode.rs
+++ b/rust/rhg/src/exitcode.rs
@@ -6,6 +6,9 @@
/// Generic abort
pub const ABORT: ExitCode = 255;
+// Abort when there is a config related error
+pub const CONFIG_ERROR_ABORT: ExitCode = 30;
+
/// Generic something completed but did not succeed
pub const UNSUCCESSFUL: ExitCode = 1;
diff --git a/rust/rhg/src/error.rs b/rust/rhg/src/error.rs
--- a/rust/rhg/src/error.rs
+++ b/rust/rhg/src/error.rs
@@ -1,3 +1,4 @@
+use crate::exitcode;
use crate::ui::utf8_to_local;
use crate::ui::UiError;
use crate::NoRepoInCwdError;
@@ -14,7 +15,10 @@
#[derive(Debug)]
pub enum CommandError {
/// Exit with an error message and "standard" failure exit code.
- Abort { message: Vec<u8> },
+ Abort {
+ message: Vec<u8>,
+ detailed_exit_code: exitcode::ExitCode,
+ },
/// Exit with a failure exit code but no message.
Unsuccessful,
@@ -28,11 +32,19 @@
impl CommandError {
pub fn abort(message: impl AsRef<str>) -> Self {
+ CommandError::abort_with_exit_code(message, exitcode::ABORT)
+ }
+
+ pub fn abort_with_exit_code(
+ message: impl AsRef<str>,
+ detailed_exit_code: exitcode::ExitCode,
+ ) -> Self {
CommandError::Abort {
// TODO: bytes-based (instead of Unicode-based) formatting
// of error messages to handle non-UTF-8 filenames etc:
// https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output
message: utf8_to_local(message.as_ref()).into(),
+ detailed_exit_code: detailed_exit_code,
}
}
@@ -64,7 +76,10 @@
impl From<ConfigValueParseError> for CommandError {
fn from(error: ConfigValueParseError) -> Self {
- CommandError::abort(error.to_string())
+ CommandError::abort_with_exit_code(
+ error.to_string(),
+ exitcode::CONFIG_ERROR_ABORT,
+ )
}
}
@@ -85,6 +100,7 @@
b"abort: repository {} not found",
get_bytes_from_path(at)
),
+ detailed_exit_code: exitcode::ABORT,
},
RepoError::ConfigParseError(error) => error.into(),
RepoError::Other(error) => error.into(),
@@ -100,6 +116,7 @@
b"abort: no repository found in '{}' (.hg not found)!",
get_bytes_from_path(cwd)
),
+ detailed_exit_code: exitcode::ABORT,
}
}
}
@@ -132,6 +149,7 @@
line_message,
message
),
+ detailed_exit_code: exitcode::CONFIG_ERROR_ABORT,
}
}
}
To: pulkit, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
More information about the Mercurial-devel
mailing list