cli: don't call process::exit() in create_ui()

This patch move the call to `process::exit()` out of `create_ui()` by
letting that function return a `(Ui, Result<(), CommandError>)`.
This commit is contained in:
Martin von Zweigbergk 2022-09-24 07:15:23 -07:00 committed by Martin von Zweigbergk
parent cc30cb6ca8
commit 4f0ccedd31
4 changed files with 31 additions and 32 deletions

View file

@ -17,7 +17,7 @@ use std::path::Path;
use clap::{FromArgMatches, Subcommand};
use git2::Repository;
use jujutsu::cli_util::{create_ui, parse_args, report_command_error, CommandError};
use jujutsu::cli_util::{create_ui, handle_command_result, parse_args, CommandError};
use jujutsu::commands::{default_app, run_command};
use jujutsu::ui::Ui;
use jujutsu_lib::backend::{
@ -61,11 +61,9 @@ fn run(ui: &mut Ui) -> Result<(), CommandError> {
}
fn main() {
let mut ui = create_ui();
let exit_code = match run(&mut ui) {
Ok(()) => 0,
Err(err) => report_command_error(&mut ui, err),
};
let (mut ui, result) = create_ui();
let result = result.and_then(|()| run(&mut ui));
let exit_code = handle_command_result(&mut ui, result);
std::process::exit(exit_code);
}

View file

@ -14,7 +14,7 @@
use clap::{FromArgMatches, Subcommand};
use jujutsu::cli_util::{
create_ui, parse_args, report_command_error, short_commit_description, CommandError,
create_ui, handle_command_result, parse_args, short_commit_description, CommandError,
};
use jujutsu::commands::{default_app, run_command};
use jujutsu::ui::Ui;
@ -59,10 +59,8 @@ fn run(ui: &mut Ui) -> Result<(), CommandError> {
}
fn main() {
let mut ui = create_ui();
let exit_code = match run(&mut ui) {
Ok(()) => 0,
Err(err) => report_command_error(&mut ui, err),
};
let (mut ui, result) = create_ui();
let result = result.and_then(|()| run(&mut ui));
let exit_code = handle_command_result(&mut ui, result);
std::process::exit(exit_code);
}

View file

@ -49,6 +49,7 @@ use crate::ui::{ColorChoice, FilePathParseError, Ui};
pub enum CommandError {
UserError(String),
ConfigError(String),
/// Invalid command line
CliError(String),
BrokenPipe,
@ -68,7 +69,7 @@ impl From<std::io::Error> for CommandError {
impl From<config::ConfigError> for CommandError {
fn from(err: config::ConfigError) -> Self {
CommandError::UserError(format!("Config error: {err}"))
CommandError::ConfigError(err.to_string())
}
}
@ -1135,16 +1136,14 @@ pub struct GlobalArgs {
pub color: Option<ColorChoice>,
}
pub fn create_ui() -> Ui<'static> {
pub fn create_ui() -> (Ui<'static>, Result<(), CommandError>) {
// TODO: We need to do some argument parsing here, at least for things like
// --config, and for reading user configs from the repo pointed to by
// -R.
// --config, and for reading user configs from the repo pointed to by -R.
match read_config() {
Ok(user_settings) => Ui::for_terminal(user_settings),
Ok(user_settings) => (Ui::for_terminal(user_settings), Ok(())),
Err(err) => {
let mut ui = Ui::for_terminal(UserSettings::default());
ui.write_error(&format!("Config error: {}\n", err)).unwrap();
std::process::exit(1);
let ui = Ui::for_terminal(UserSettings::default());
(ui, Err(CommandError::ConfigError(err.to_string())))
}
}
}
@ -1264,18 +1263,24 @@ pub fn parse_args<'help>(
// TODO: Return std::process::ExitCode instead, once our MSRV is >= 1.61
#[must_use]
pub fn report_command_error(ui: &mut Ui, err: CommandError) -> i32 {
match err {
CommandError::UserError(message) => {
pub fn handle_command_result(ui: &mut Ui, result: Result<(), CommandError>) -> i32 {
match result {
Ok(()) => 0,
Err(CommandError::UserError(message)) => {
ui.write_error(&format!("Error: {}\n", message)).unwrap();
1
}
CommandError::CliError(message) => {
Err(CommandError::ConfigError(message)) => {
ui.write_error(&format!("Config error: {}\n", message))
.unwrap();
1
}
Err(CommandError::CliError(message)) => {
ui.write_error(&format!("Error: {}\n", message)).unwrap();
2
}
CommandError::BrokenPipe => std::process::exit(3),
CommandError::InternalError(message) => {
Err(CommandError::BrokenPipe) => std::process::exit(3),
Err(CommandError::InternalError(message)) => {
ui.write_error(&format!("Internal error: {}\n", message))
.unwrap();
255

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use jujutsu::cli_util::{create_ui, parse_args, report_command_error, CommandError};
use jujutsu::cli_util::{create_ui, handle_command_result, parse_args, CommandError};
use jujutsu::commands::{default_app, run_command};
use jujutsu::ui::Ui;
@ -23,10 +23,8 @@ fn run(ui: &mut Ui) -> Result<(), CommandError> {
}
fn main() {
let mut ui = create_ui();
let exit_code = match run(&mut ui) {
Ok(()) => 0,
Err(err) => report_command_error(&mut ui, err),
};
let (mut ui, result) = create_ui();
let result = result.and_then(|()| run(&mut ui));
let exit_code = handle_command_result(&mut ui, result);
std::process::exit(exit_code);
}