mirror of
https://git.proxmox.com/git/proxmox
synced 2025-05-29 07:17:42 +00:00
src/cli/command.rs: avoid creating a tokio runtime by making run_cli_command async
This commit is contained in:
parent
2ef0e795a7
commit
26d5d3e680
@ -23,7 +23,7 @@ pub const OUTPUT_FORMAT: Schema = StringSchema::new("Output format.")
|
|||||||
.format(&ApiStringFormat::Enum(&["text", "json", "json-pretty"]))
|
.format(&ApiStringFormat::Enum(&["text", "json", "json-pretty"]))
|
||||||
.schema();
|
.schema();
|
||||||
|
|
||||||
fn handle_simple_command(
|
async fn handle_simple_command(
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
cli_cmd: &CliCommand,
|
cli_cmd: &CliCommand,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
@ -60,9 +60,8 @@ fn handle_simple_command(
|
|||||||
},
|
},
|
||||||
ApiHandler::Async(handler) => {
|
ApiHandler::Async(handler) => {
|
||||||
let future = (handler)(params, &cli_cmd.info, &mut rpcenv);
|
let future = (handler)(params, &cli_cmd.info, &mut rpcenv);
|
||||||
let mut rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
|
|
||||||
match rt.block_on(future) {
|
match future.await {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
if value != Value::Null {
|
if value != Value::Null {
|
||||||
println!("Result: {}", serde_json::to_string_pretty(&value).unwrap());
|
println!("Result: {}", serde_json::to_string_pretty(&value).unwrap());
|
||||||
@ -84,51 +83,57 @@ fn handle_simple_command(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_nested_command(
|
async fn handle_nested_command(
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
def: &CliCommandMap,
|
def: &CliCommandMap,
|
||||||
mut args: Vec<String>,
|
mut args: Vec<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if args.is_empty() {
|
|
||||||
let mut cmds: Vec<&String> = def.commands.keys().collect();
|
|
||||||
cmds.sort();
|
|
||||||
|
|
||||||
let list = cmds.iter().fold(String::new(), |mut s, item| {
|
let mut map = def;
|
||||||
if !s.is_empty() {
|
let mut prefix = prefix.to_string();
|
||||||
s += ", ";
|
|
||||||
}
|
|
||||||
s += item;
|
|
||||||
s
|
|
||||||
});
|
|
||||||
|
|
||||||
let err_msg = format!("no command specified.\nPossible commands: {}", list);
|
// Note: Avoid async recursive function, because current rust compiler cant handle that
|
||||||
print_nested_usage_error(prefix, def, &err_msg);
|
loop {
|
||||||
return Err(format_err!("{}", err_msg));
|
if args.is_empty() {
|
||||||
}
|
let mut cmds: Vec<&String> = def.commands.keys().collect();
|
||||||
|
cmds.sort();
|
||||||
|
|
||||||
let command = args.remove(0);
|
let list = cmds.iter().fold(String::new(), |mut s, item| {
|
||||||
|
if !s.is_empty() {
|
||||||
|
s += ", ";
|
||||||
|
}
|
||||||
|
s += item;
|
||||||
|
s
|
||||||
|
});
|
||||||
|
|
||||||
let (_, sub_cmd) = match def.find_command(&command) {
|
let err_msg = format!("no command specified.\nPossible commands: {}", list);
|
||||||
Some(cmd) => cmd,
|
print_nested_usage_error(&prefix, def, &err_msg);
|
||||||
None => {
|
|
||||||
let err_msg = format!("no such command '{}'", command);
|
|
||||||
print_nested_usage_error(prefix, def, &err_msg);
|
|
||||||
return Err(format_err!("{}", err_msg));
|
return Err(format_err!("{}", err_msg));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let new_prefix = format!("{} {}", prefix, command);
|
let command = args.remove(0);
|
||||||
|
|
||||||
match sub_cmd {
|
let (_, sub_cmd) = match map.find_command(&command) {
|
||||||
CommandLineInterface::Simple(cli_cmd) => {
|
Some(cmd) => cmd,
|
||||||
handle_simple_command(&new_prefix, cli_cmd, args)?;
|
None => {
|
||||||
}
|
let err_msg = format!("no such command '{}'", command);
|
||||||
CommandLineInterface::Nested(map) => {
|
print_nested_usage_error(&prefix, def, &err_msg);
|
||||||
handle_nested_command(&new_prefix, map, args)?;
|
return Err(format_err!("{}", err_msg));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
prefix = format!("{} {}", prefix, command);
|
||||||
|
|
||||||
|
match sub_cmd {
|
||||||
|
CommandLineInterface::Simple(cli_cmd) => {
|
||||||
|
return handle_simple_command(&prefix, cli_cmd, args).await;
|
||||||
|
}
|
||||||
|
CommandLineInterface::Nested(new_map) => {
|
||||||
|
map = new_map
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_METHOD_COMMAND_HELP: ApiMethod = ApiMethod::new(
|
const API_METHOD_COMMAND_HELP: ApiMethod = ApiMethod::new(
|
||||||
@ -198,7 +203,7 @@ pub(crate) fn help_command_def() -> CliCommand {
|
|||||||
///
|
///
|
||||||
/// This command gets the command line ``args`` and tries to invoke
|
/// This command gets the command line ``args`` and tries to invoke
|
||||||
/// the corresponding API handler.
|
/// the corresponding API handler.
|
||||||
pub fn handle_command(
|
pub async fn handle_command(
|
||||||
def: Arc<CommandLineInterface>,
|
def: Arc<CommandLineInterface>,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
@ -206,8 +211,8 @@ pub fn handle_command(
|
|||||||
set_help_context(Some(def.clone()));
|
set_help_context(Some(def.clone()));
|
||||||
|
|
||||||
let result = match &*def {
|
let result = match &*def {
|
||||||
CommandLineInterface::Simple(ref cli_cmd) => handle_simple_command(&prefix, &cli_cmd, args),
|
CommandLineInterface::Simple(ref cli_cmd) => handle_simple_command(&prefix, &cli_cmd, args).await,
|
||||||
CommandLineInterface::Nested(ref map) => handle_nested_command(&prefix, &map, args),
|
CommandLineInterface::Nested(ref map) => handle_nested_command(&prefix, &map, args).await,
|
||||||
};
|
};
|
||||||
|
|
||||||
set_help_context(None);
|
set_help_context(None);
|
||||||
@ -227,7 +232,7 @@ pub fn handle_command(
|
|||||||
/// - ``bashcomplete``: Output bash completions instead of running the command.
|
/// - ``bashcomplete``: Output bash completions instead of running the command.
|
||||||
/// - ``printdoc``: Output ReST documentation.
|
/// - ``printdoc``: Output ReST documentation.
|
||||||
///
|
///
|
||||||
pub fn run_cli_command<C: Into<CommandLineInterface>>(def: C) {
|
pub async fn run_cli_command<C: Into<CommandLineInterface>>(def: C) {
|
||||||
let def = match def.into() {
|
let def = match def.into() {
|
||||||
CommandLineInterface::Simple(cli_cmd) => CommandLineInterface::Simple(cli_cmd),
|
CommandLineInterface::Simple(cli_cmd) => CommandLineInterface::Simple(cli_cmd),
|
||||||
CommandLineInterface::Nested(map) => CommandLineInterface::Nested(map.insert_help()),
|
CommandLineInterface::Nested(map) => CommandLineInterface::Nested(map.insert_help()),
|
||||||
@ -260,7 +265,7 @@ pub fn run_cli_command<C: Into<CommandLineInterface>>(def: C) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if handle_command(Arc::new(def), &prefix, args).is_err() {
|
if handle_command(Arc::new(def), &prefix, args).await.is_err() {
|
||||||
std::process::exit(-1);
|
std::process::exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user