clidispatch: make dispatcher better handle commands.force-rust

Summary: Previously Rust commands had to set the command name when indicating they had to fall back to Python. For instance, if one wanted to prevent the Rust clone command falling back to Python when setting `commands.force-rust=clone`, one had to return a `errors::FallbackToPython("clone")` error. This makes the dispatcher use the first alias in the list of aliases as the main name for commands instead of the string in the `FallbackToPython` error.

Reviewed By: quark-zju

Differential Revision: D39452275

fbshipit-source-id: d03dc6c420241d661dbedff96baaf9bf2ff54457
This commit is contained in:
Saul Gutierrez 2022-09-14 18:43:08 -07:00 committed by Facebook GitHub Bot
parent 020555df32
commit 4238db79bc
5 changed files with 35 additions and 10 deletions

View File

@ -71,6 +71,14 @@ impl CommandDefinition {
pub fn synopsis(&self) -> Option<&str> {
self.synopsis.as_deref()
}
pub fn main_alias(&self) -> &str {
if let Some(name) = self.aliases.split('|').next() {
name
} else {
""
}
}
}
#[derive(Default)]

View File

@ -219,7 +219,7 @@ impl Dispatcher {
if let Ok(config) =
configparser::hg::load(None, &global_opts.config, &global_opts.configfile)
{
Err(errors::triage_error(&config, err))
Err(errors::triage_error(&config, err, None))
} else {
Err(err)
}

View File

@ -83,7 +83,11 @@ pub fn print_error(err: &anyhow::Error, io: &crate::io::IO, _args: &[String]) {
}
/// Optionally transform an error into something more friendly to the user.
pub fn triage_error(config: &ConfigSet, cmd_err: anyhow::Error) -> anyhow::Error {
pub fn triage_error(
config: &ConfigSet,
cmd_err: anyhow::Error,
command_name: Option<&str>,
) -> anyhow::Error {
if types::errors::is_network_error(&cmd_err)
&& config
.get_or_default("experimental", "network-doctor")
@ -103,10 +107,11 @@ pub fn triage_error(config: &ConfigSet, cmd_err: anyhow::Error) -> anyhow::Error
}
}
} else {
if let Some(FallbackToPython(command_name)) = cmd_err.downcast_ref::<FallbackToPython>() {
if config
.get_or_default::<Vec<String>>("commands", "force-rust")
.map_or(false, |config| config.contains(&command_name.to_string()))
if let Some(command_name) = command_name {
if cmd_err.is::<FallbackToPython>()
&& config
.get_or_default::<Vec<String>>("commands", "force-rust")
.map_or(false, |config| config.contains(&command_name.to_string()))
{
return anyhow::Error::new(FailedFallbackToPython);
}

View File

@ -210,7 +210,9 @@ fn dispatch_command(
let config = dispatcher.config();
let mut fell_back = false;
let exit_code = match dispatch_res.map_err(|err| errors::triage_error(config, err)) {
let exit_code = match dispatch_res
.map_err(|err| errors::triage_error(config, err, command.map(|c| c.main_alias())))
{
Ok(exit_code) => exit_code as i32,
Err(err) => {
let should_fallback = err.is::<errors::FallbackToPython>() ||
@ -248,12 +250,12 @@ fn dispatch_command(
if let Some(command) = command {
let hooks_with_prefix =
|prefix: String| -> Vec<minibytes::Text> { config.keys_prefixed("hooks", &prefix) };
let mut hooks = hooks_with_prefix(format!("pre-{}.", command.aliases()));
let mut hooks = hooks_with_prefix(format!("pre-{}.", command.main_alias()));
if exit_code > 0 {
let mut names = hooks_with_prefix(format!("fail-{}.", command.aliases()));
let mut names = hooks_with_prefix(format!("fail-{}.", command.main_alias()));
hooks.append(&mut names);
} else {
let mut names = hooks_with_prefix(format!("post-{}.", command.aliases()));
let mut names = hooks_with_prefix(format!("post-{}.", command.main_alias()));
hooks.append(&mut names);
}

View File

@ -2,9 +2,19 @@
#debugruntest-compatible
$ configure modern
$ setconfig workingcopy.use-rust=True
$ setconfig edenapi.url=https://test_fail/foo
$ hg init testrepo
$ cd testrepo
Test failed fallback
$ hg --config commands.force-rust=clone clone -u yadayada aoeu snth
[197]
$ hg --config commands.force-rust=config config commands.force-rust -T "*shrugs*"
[197]
$ touch something
$ hg addremove
adding something
$ hg commit -m "Added something"
$ hg --config commands.force-rust=status st
[197]