From 69cbfc8375a00b41cae2128727d2348b55f8c101 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 7 Jul 2024 23:25:02 -0400 Subject: [PATCH 01/21] [src/lib/{mod,cli,cli_parser,runner,descriptor/mod}.rs] Make `pub`lic useful symbols for use `cargo-make` as library --- src/lib/cli.rs | 2 +- src/lib/cli_parser.rs | 2 +- src/lib/descriptor/mod.rs | 2 +- src/lib/mod.rs | 2 +- src/lib/runner.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/cli.rs b/src/lib/cli.rs index d0e74358..9032bc82 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -170,7 +170,7 @@ fn run(cli_args: CliArgs, global_config: &GlobalConfig) { } /// Handles the command line arguments and executes the runner. -pub(crate) fn run_cli(command_name: String, sub_command: bool) { +pub fn run_cli(command_name: String, sub_command: bool) { let global_config = config::load(); let cli_args = cli_parser::parse(&global_config, &command_name, sub_command); diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index 4169a788..1c756f12 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -500,7 +500,7 @@ pub(crate) fn parse_args( Err(error) => { let help_text = cliparser::help(&spec); println!("{}\n{}", &error, help_text); - exit(); + exit() } } } diff --git a/src/lib/descriptor/mod.rs b/src/lib/descriptor/mod.rs index 882351f1..040ecaf1 100755 --- a/src/lib/descriptor/mod.rs +++ b/src/lib/descriptor/mod.rs @@ -578,7 +578,7 @@ fn load_cargo_aliases(config: &mut Config) { /// the default descriptor.
If one of the descriptor requires a newer /// version of cargo-make, returns an error with the minimum version required by /// the descriptor. -pub(crate) fn load( +pub fn load( file_name: &str, force: bool, env_map: Option>, diff --git a/src/lib/mod.rs b/src/lib/mod.rs index c98aad53..a7706856 100755 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -68,7 +68,7 @@ mod plugin; mod profile; mod proxy_task; mod recursion_level; -mod runner; +pub mod runner; mod scriptengine; mod storage; mod time_summary; diff --git a/src/lib/runner.rs b/src/lib/runner.rs index c774314a..0ba358b3 100755 --- a/src/lib/runner.rs +++ b/src/lib/runner.rs @@ -609,7 +609,7 @@ fn run_protected_flow(flow_info: &FlowInfo, flow_state: Rc>) /// /// * Create an execution plan based on the requested task and its dependencies /// * Run all tasks defined in the execution plan -pub(crate) fn run( +pub fn run( config: Config, task: &str, env_info: EnvInfo, From 6cf59426a6e33ebaf5a769f88f5dda51a7e4cc1f Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Mon, 8 Jul 2024 12:44:38 -0400 Subject: [PATCH 02/21] [src/lib/**.rs] Make `pub`lic useful symbols for use `cargo-make` as library --- src/lib/cli.rs | 2 +- src/lib/cli_commands/list_steps.rs | 4 ++-- src/lib/cli_commands/mod.rs | 4 ++-- src/lib/cli_commands/print_steps.rs | 2 +- src/lib/cli_parser.rs | 6 +++--- src/lib/config.rs | 8 ++++---- src/lib/mod.rs | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lib/cli.rs b/src/lib/cli.rs index 9032bc82..7760b974 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -31,7 +31,7 @@ pub(crate) static DEFAULT_LOG_LEVEL: &str = "info"; pub(crate) static DEFAULT_TASK_NAME: &str = "default"; pub(crate) static DEFAULT_OUTPUT_FORMAT: &str = "default"; -fn run(cli_args: CliArgs, global_config: &GlobalConfig) { +pub fn run(cli_args: CliArgs, global_config: &GlobalConfig) { let start_time = SystemTime::now(); recursion_level::increment(); diff --git a/src/lib/cli_commands/list_steps.rs b/src/lib/cli_commands/list_steps.rs index daf13908..a49f7c15 100644 --- a/src/lib/cli_commands/list_steps.rs +++ b/src/lib/cli_commands/list_steps.rs @@ -13,7 +13,7 @@ use crate::io; use crate::types::{Config, DeprecationInfo}; use std::collections::{BTreeMap, BTreeSet}; -pub(crate) fn run( +pub fn run( config: &Config, output_format: &str, output_file: &Option, @@ -186,7 +186,7 @@ pub(crate) fn create_list( } if !just_task_name { - buffer.push_str(&format!("\n")); + buffer.push('\n'); } } diff --git a/src/lib/cli_commands/mod.rs b/src/lib/cli_commands/mod.rs index 85208434..a72e91ef 100644 --- a/src/lib/cli_commands/mod.rs +++ b/src/lib/cli_commands/mod.rs @@ -4,5 +4,5 @@ //! pub(crate) mod diff_steps; -pub(crate) mod list_steps; -pub(crate) mod print_steps; +pub mod list_steps; +pub mod print_steps; diff --git a/src/lib/cli_commands/print_steps.rs b/src/lib/cli_commands/print_steps.rs index cdc5a2ff..c4540af4 100644 --- a/src/lib/cli_commands/print_steps.rs +++ b/src/lib/cli_commands/print_steps.rs @@ -61,7 +61,7 @@ fn print_default(execution_plan: &ExecutionPlan) { } /// Only prints the execution plan -pub(crate) fn print( +pub fn print( config: &Config, task: &str, output_format: &str, diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index 1c756f12..1ab7306d 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -146,7 +146,7 @@ fn get_args( cli_args } -fn create_cli(global_config: &GlobalConfig) -> CliSpec { +pub fn create_cli(global_config: &GlobalConfig) -> CliSpec { let default_task_name = match global_config.default_task_name { Some(ref value) => value.as_str(), None => &DEFAULT_TASK_NAME, @@ -468,7 +468,7 @@ fn create_cli(global_config: &GlobalConfig) -> CliSpec { spec } -pub(crate) fn parse_args( +pub fn parse_args( global_config: &GlobalConfig, command_name: &str, sub_command: bool, @@ -505,7 +505,7 @@ pub(crate) fn parse_args( } } -pub(crate) fn parse( +pub fn parse( global_config: &GlobalConfig, command_name: &str, sub_command: bool, diff --git a/src/lib/config.rs b/src/lib/config.rs index 8e4498d6..ea1a1957 100644 --- a/src/lib/config.rs +++ b/src/lib/config.rs @@ -13,14 +13,14 @@ use fsio::file::read_text_file; use fsio::path::from_path::FromPath; use std::path::{Path, PathBuf}; -static CONFIG_FILE: &'static str = "config.toml"; +pub static CONFIG_FILE: &'static str = "config.toml"; -fn get_config_directory() -> Option { +pub fn get_config_directory() -> Option { let os_directory = dirs_next::config_dir(); storage::get_storage_directory(os_directory, CONFIG_FILE, true) } -fn load_from_path(directory: PathBuf) -> GlobalConfig { +pub fn load_from_path(directory: PathBuf) -> GlobalConfig { let file_path = Path::new(&directory).join(CONFIG_FILE); debug!("Loading config from: {:#?}", &file_path); @@ -47,7 +47,7 @@ fn load_from_path(directory: PathBuf) -> GlobalConfig { } /// Returns the configuration -pub(crate) fn load() -> GlobalConfig { +pub fn load() -> GlobalConfig { match get_config_directory() { Some(directory) => load_from_path(directory), None => GlobalConfig::new(), diff --git a/src/lib/mod.rs b/src/lib/mod.rs index a7706856..917a0cba 100755 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -50,12 +50,12 @@ mod test; pub mod types; mod cache; -mod cli; -mod cli_commands; -mod cli_parser; +pub mod cli; +pub mod cli_commands; +pub mod cli_parser; mod command; mod condition; -mod config; +pub mod config; mod descriptor; mod environment; mod execution_plan; From 2234422b060ab8410323dd09ff6fecb42e5f24c9 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Thu, 11 Jul 2024 21:52:15 -0400 Subject: [PATCH 03/21] [src/lib/*.rs] Percolate exit codes around --- Cargo.lock | 1 + Cargo.toml | 3 +- src/lib/cli.rs | 11 +++-- src/lib/cli_parser.rs | 26 ++++------- src/lib/cli_parser_test.rs | 96 +++++++++++++++++++------------------- src/lib/cli_test.rs | 35 ++++++++------ src/lib/logger.rs | 15 ++---- src/lib/mod.rs | 4 +- 8 files changed, 96 insertions(+), 95 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60d35463..afccbe98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,6 +150,7 @@ dependencies = [ "dirs-next", "duckscript", "duckscriptsdk", + "either", "envmnt", "expect-test", "fern", diff --git a/Cargo.toml b/Cargo.toml index cb75a76f..1742039a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,15 +52,16 @@ ctrlc = "^3" dirs-next = "^2" duckscript = "^0.8.0" duckscriptsdk = { version = "^0.9.3", default-features = false } +either = "1.13.0" envmnt = "^0.10.4" fern = "^0.6" fsio = { version = "^0.4", features = ["temp-path"] } git_info = "^0.1.2" glob = "^0.3.1" home = "^0.5" +ignore = "^0.4" indexmap = { version = "^2", features = ["serde"] } itertools = "^0.13" -ignore = "^0.4" lenient_semver = "^0.4.2" log = "^0.4" once_cell = "^1.19.0" diff --git a/src/lib/cli.rs b/src/lib/cli.rs index 7760b974..9fed804d 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -22,6 +22,7 @@ use crate::toolchain; use crate::types::{CliArgs, GlobalConfig}; use crate::version; use std::time::SystemTime; +use either::{Either, try_left}; pub(crate) static VERSION: &str = env!("CARGO_PKG_VERSION"); pub(crate) static AUTHOR: &str = env!("CARGO_PKG_AUTHORS"); @@ -31,7 +32,7 @@ pub(crate) static DEFAULT_LOG_LEVEL: &str = "info"; pub(crate) static DEFAULT_TASK_NAME: &str = "default"; pub(crate) static DEFAULT_OUTPUT_FORMAT: &str = "default"; -pub fn run(cli_args: CliArgs, global_config: &GlobalConfig) { +pub fn run(cli_args: CliArgs, global_config: &GlobalConfig) -> Either { let start_time = SystemTime::now(); recursion_level::increment(); @@ -167,13 +168,15 @@ pub fn run(cli_args: CliArgs, global_config: &GlobalConfig) { time_summary_vec, ); } + Either::Right(std::process::ExitCode::SUCCESS) } /// Handles the command line arguments and executes the runner. -pub fn run_cli(command_name: String, sub_command: bool) { +pub fn run_cli(command_name: String, sub_command: bool) -> Either { let global_config = config::load(); - let cli_args = cli_parser::parse(&global_config, &command_name, sub_command); + let cli_args = try_left!(cli_parser::parse(&global_config, &command_name, sub_command)); - run(cli_args, &global_config); + run(cli_args.clone(), &global_config); + Either::Left(cli_args) } diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index 1ab7306d..eafc2639 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -17,18 +17,8 @@ use cliparser::types::{ CliSpecMetaInfo, PositionalArgument, }; -#[cfg(test)] -fn exit() -> ! { - panic!("{}", "exit test"); -} - -#[cfg(not(test))] -use std::process; -#[cfg(not(test))] -fn exit() -> ! { - process::exit(0); -} +use either::Either; fn get_args( cli_parsed: &CliParsed, @@ -472,8 +462,8 @@ pub fn parse_args( global_config: &GlobalConfig, command_name: &str, sub_command: bool, - args: Option>, -) -> CliArgs { + args: Option> +) -> Either { let spec = create_cli(&global_config); let parse_result = match args { @@ -487,20 +477,20 @@ pub fn parse_args( // generate help text let help_text = cliparser::help(&spec); println!("{}", help_text); - exit(); + return Either::Right(std::process::ExitCode::from(std::process::ExitCode::SUCCESS)) } else if cli_parsed.arguments.contains("version") { // generate version text let version_text = cliparser::version(&spec); println!("{}", version_text); - exit(); + return Either::Right(std::process::ExitCode::SUCCESS) } - get_args(&cli_parsed, &global_config, command_name, sub_command) + return Either::Left(get_args(&cli_parsed, &global_config, command_name, sub_command)) } Err(error) => { let help_text = cliparser::help(&spec); println!("{}\n{}", &error, help_text); - exit() + return Either::Right(std::process::ExitCode::FAILURE) } } } @@ -509,7 +499,7 @@ pub fn parse( global_config: &GlobalConfig, command_name: &str, sub_command: bool, -) -> CliArgs { +) -> Either { parse_args(global_config, command_name, sub_command, None) } diff --git a/src/lib/cli_parser_test.rs b/src/lib/cli_parser_test.rs index ae85c7cc..139232f1 100644 --- a/src/lib/cli_parser_test.rs +++ b/src/lib/cli_parser_test.rs @@ -1,6 +1,6 @@ use super::*; -fn default_parse_cli_args(mut args: Vec<&str>) -> CliArgs { +fn default_parse_cli_args(mut args: Vec<&str>) -> Either { let global_config = GlobalConfig::new(); args.insert(0, "makers"); parse_args(&global_config, "makers", false, Some(args)) @@ -59,7 +59,7 @@ fn parse_args_makers() { let expected = default_parsed_cli_args(); - assert_cli_args(&cli_args, &expected); + assert_cli_args(&cli_args.left().unwrap(), &expected); } #[test] @@ -70,7 +70,7 @@ fn parse_args_cargo_make() { let mut expected = default_parsed_cli_args(); expected.command = "cargo make".to_string(); - assert_cli_args(&cli_args, &expected); + assert_cli_args(&cli_args.left().unwrap(), &expected); } #[test] @@ -104,44 +104,44 @@ fn parse_args_makefile() { let mut expected = default_parsed_cli_args(); expected.build_file = Some("./mymakefile.toml".to_string()); - assert_cli_args(&cli_args, &expected); + assert_cli_args(&cli_args.left().unwrap(), &expected); cli_args = default_parse_cli_args(vec!["--makefile", "./mymakefile.toml", "taskname"]); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); - assert_cli_args(&cli_args, &expected); + assert_cli_args(&cli_args.left().unwrap(), &expected); } #[test] fn parse_args_task() { - let mut cli_args = default_parse_cli_args(vec!["--task", "sometask"]); + let mut cli_args = default_parse_cli_args(vec!["--task", "sometask"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.task = "sometask".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-t", "sometask"]); + cli_args = default_parse_cli_args(vec!["-t", "sometask"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["sometask"]); + cli_args = default_parse_cli_args(vec!["sometask"]).left().unwrap(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_profile() { - let mut cli_args = default_parse_cli_args(vec!["--profile", "someprofile"]); + let mut cli_args = default_parse_cli_args(vec!["--profile", "someprofile"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.profile = Some("someprofile".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-p", "someprofile"]); + cli_args = default_parse_cli_args(vec!["-p", "someprofile"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--profile", "someprofile", "taskname"]); + cli_args = default_parse_cli_args(vec!["--profile", "someprofile", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -149,7 +149,7 @@ fn parse_args_profile() { #[test] fn parse_args_cwd() { - let cli_args = default_parse_cli_args(vec!["--cwd", "./mydir/subdir/"]); + let cli_args = default_parse_cli_args(vec!["--cwd", "./mydir/subdir/"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.cwd = Some("./mydir/subdir/".to_string()); @@ -159,7 +159,7 @@ fn parse_args_cwd() { #[test] fn parse_args_no_workspace() { - let cli_args = default_parse_cli_args(vec!["--no-workspace"]); + let cli_args = default_parse_cli_args(vec!["--no-workspace"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_workspace = true; @@ -169,7 +169,7 @@ fn parse_args_no_workspace() { #[test] fn parse_args_allow_private() { - let cli_args = default_parse_cli_args(vec!["--allow-private"]); + let cli_args = default_parse_cli_args(vec!["--allow-private"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.allow_private = true; @@ -179,7 +179,7 @@ fn parse_args_allow_private() { #[test] fn parse_args_skip_init_end_tasks() { - let cli_args = default_parse_cli_args(vec!["--skip-init-end-tasks"]); + let cli_args = default_parse_cli_args(vec!["--skip-init-end-tasks"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.skip_init_end_tasks = true; @@ -189,14 +189,14 @@ fn parse_args_skip_init_end_tasks() { #[test] fn parse_args_skip_tasks() { - let mut cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*"]); + let mut cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.skip_tasks_pattern = Some("pre-.*".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*", "taskname"]); + cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -204,38 +204,38 @@ fn parse_args_skip_tasks() { #[test] fn parse_args_env_file() { - let mut cli_args = default_parse_cli_args(vec!["--env-file", "./.env"]); + let mut cli_args = default_parse_cli_args(vec!["--env-file", "./.env"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.env_file = Some("./.env".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file=./.env"]); + cli_args = default_parse_cli_args(vec!["--env-file=./.env"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file", "./.env", "taskname"]); + cli_args = default_parse_cli_args(vec!["--env-file", "./.env", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file=./.env", "taskname"]); + cli_args = default_parse_cli_args(vec!["--env-file=./.env", "taskname"]).left().unwrap(); assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_env() { - let mut cli_args = default_parse_cli_args(vec!["--env", "K=V"]); + let mut cli_args = default_parse_cli_args(vec!["--env", "K=V"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.env = Some(vec!["K=V".to_string()]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-e", "K=V"]); + cli_args = default_parse_cli_args(vec!["-e", "K=V"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3"]); + cli_args = default_parse_cli_args(vec!["-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3"]).left().unwrap(); expected.env = Some(vec![ "K1=V1".to_string(), "K2=V2".to_string(), @@ -245,7 +245,7 @@ fn parse_args_env() { cli_args = default_parse_cli_args(vec![ "-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3", "taskname", - ]); + ]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -253,17 +253,17 @@ fn parse_args_env() { #[test] fn parse_args_loglevel() { - let mut cli_args = default_parse_cli_args(vec!["--loglevel", "verbose"]); + let mut cli_args = default_parse_cli_args(vec!["--loglevel", "verbose"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "verbose".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-l", "verbose"]); + cli_args = default_parse_cli_args(vec!["-l", "verbose"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--loglevel", "verbose", "taskname"]); + cli_args = default_parse_cli_args(vec!["--loglevel", "verbose", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -271,20 +271,20 @@ fn parse_args_loglevel() { #[test] fn parse_args_verbose() { - let mut cli_args = default_parse_cli_args(vec!["--verbose"]); + let mut cli_args = default_parse_cli_args(vec!["--verbose"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "verbose".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-v"]); + cli_args = default_parse_cli_args(vec!["-v"]).left().unwrap(); assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_quiet() { - let cli_args = default_parse_cli_args(vec!["--quiet"]); + let cli_args = default_parse_cli_args(vec!["--quiet"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "error".to_string(); @@ -294,7 +294,7 @@ fn parse_args_quiet() { #[test] fn parse_args_no_color() { - let cli_args = default_parse_cli_args(vec!["--no-color"]); + let cli_args = default_parse_cli_args(vec!["--no-color"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_color = true; @@ -304,7 +304,7 @@ fn parse_args_no_color() { #[test] fn parse_args_time_summary() { - let cli_args = default_parse_cli_args(vec!["--time-summary"]); + let cli_args = default_parse_cli_args(vec!["--time-summary"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.print_time_summary = true; @@ -314,7 +314,7 @@ fn parse_args_time_summary() { #[test] fn parse_args_experimental() { - let cli_args = default_parse_cli_args(vec!["--experimental"]); + let cli_args = default_parse_cli_args(vec!["--experimental"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.experimental = true; @@ -324,7 +324,7 @@ fn parse_args_experimental() { #[test] fn parse_args_disable_check_for_updates() { - let cli_args = default_parse_cli_args(vec!["--disable-check-for-updates"]); + let cli_args = default_parse_cli_args(vec!["--disable-check-for-updates"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_check_for_updates = true; @@ -334,14 +334,14 @@ fn parse_args_disable_check_for_updates() { #[test] fn parse_args_output_format() { - let mut cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete"]); + let mut cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.output_format = "autocomplete".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete", "taskname"]); + cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -349,14 +349,14 @@ fn parse_args_output_format() { #[test] fn parse_args_output_file() { - let mut cli_args = default_parse_cli_args(vec!["--output-file", "./out"]); + let mut cli_args = default_parse_cli_args(vec!["--output-file", "./out"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.output_file = Some("./out".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--output-file", "./out", "taskname"]); + cli_args = default_parse_cli_args(vec!["--output-file", "./out", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -364,7 +364,7 @@ fn parse_args_output_file() { #[test] fn parse_args_print_steps() { - let cli_args = default_parse_cli_args(vec!["--print-steps"]); + let cli_args = default_parse_cli_args(vec!["--print-steps"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.print_only = true; @@ -374,7 +374,7 @@ fn parse_args_print_steps() { #[test] fn parse_args_list_all_steps() { - let cli_args = default_parse_cli_args(vec!["--list-all-steps"]); + let cli_args = default_parse_cli_args(vec!["--list-all-steps"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.list_all_steps = true; @@ -384,14 +384,14 @@ fn parse_args_list_all_steps() { #[test] fn parse_args_list_category_steps() { - let mut cli_args = default_parse_cli_args(vec!["--list-category-steps", "build"]); + let mut cli_args = default_parse_cli_args(vec!["--list-category-steps", "build"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.list_category_steps = Some("build".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--list-category-steps", "build", "taskname"]); + cli_args = default_parse_cli_args(vec!["--list-category-steps", "build", "taskname"]).left().unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -399,7 +399,7 @@ fn parse_args_list_category_steps() { #[test] fn parse_args_diff_steps() { - let cli_args = default_parse_cli_args(vec!["--diff-steps"]); + let cli_args = default_parse_cli_args(vec!["--diff-steps"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.diff_execution_plan = true; @@ -409,7 +409,7 @@ fn parse_args_diff_steps() { #[test] fn parse_args_task_cmd() { - let mut cli_args = default_parse_cli_args(vec!["task1"]); + let mut cli_args = default_parse_cli_args(vec!["task1"]).left().unwrap(); let mut expected = default_parsed_cli_args(); expected.task = "task1".to_string(); @@ -417,13 +417,13 @@ fn parse_args_task_cmd() { assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--", "task1"]); + cli_args = default_parse_cli_args(vec!["--", "task1"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["task1", "arg1", "arg2"]); + cli_args = default_parse_cli_args(vec!["task1", "arg1", "arg2"]).left().unwrap(); expected.arguments = Some(vec!["arg1".to_string(), "arg2".to_string()]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--", "task1", "arg1", "arg2"]); + cli_args = default_parse_cli_args(vec!["--", "task1", "arg1", "arg2"]).left().unwrap(); assert_cli_args(&cli_args, &expected); } diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index de2bc78e..674afae9 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -393,7 +393,13 @@ fn run_bad_subcommand() { let cli_args = cli_parser::parse_args(&global_config, &"make".to_string(), true, Some(vec!["bad"])); - run(cli_args, &global_config); + + assert_eq!( + format!("{:?}", &cli_args.clone().right().unwrap()), + format!("{:?}", std::process::ExitCode::FAILURE) + ); + + run(cli_args.left().unwrap(), &global_config); } #[test] @@ -418,7 +424,10 @@ fn run_valid() { ]), ); - run(cli_args, &global_config); + assert_eq!( + format!("{:?}", run(cli_args.left().unwrap(), &global_config).right().unwrap()), + format!("{:?}", std::process::ExitCode::FAILURE) + ); } #[test] @@ -433,7 +442,7 @@ fn run_with_global_config() { &"make".to_string(), true, Some(vec!["cargo", "make"]), - ); + ).left().unwrap(); run(cli_args, &global_config); } @@ -457,7 +466,7 @@ fn run_log_level_override() { "error", "-v", ]), - ); + ).left().unwrap(); run(cli_args, &global_config); } @@ -484,7 +493,7 @@ fn run_set_env_values() { "-t", "empty", ]), - ); + ).left().unwrap(); envmnt::set("ENV1_TEST", "EMPTY"); envmnt::set("ENV2_TEST", "EMPTY"); @@ -520,7 +529,7 @@ fn run_set_env_via_file() { envmnt::set("ENV2_TEST", "EMPTY"); envmnt::set("ENV3_TEST", "EMPTY"); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2"); @@ -559,7 +568,7 @@ fn run_set_env_both() { envmnt::set("ENV5_TEST", "EMPTY"); envmnt::set("ENV6_TEST", "EMPTY"); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2"); @@ -595,7 +604,7 @@ fn run_print_only() { ]), ); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); } #[test] @@ -620,7 +629,7 @@ fn run_diff_steps() { ]), ); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); } #[test] @@ -640,7 +649,7 @@ fn run_protected_flow_example() { ]), ); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); } #[test] @@ -661,7 +670,7 @@ fn run_no_task_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), ""); } @@ -687,7 +696,7 @@ fn run_set_task_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), @@ -710,7 +719,7 @@ fn run_set_task_var_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(cli_args, &global_config); + run(cli_args.left().unwrap(), &global_config); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), diff --git a/src/lib/logger.rs b/src/lib/logger.rs index 0b73a0b7..9cd5be99 100755 --- a/src/lib/logger.rs +++ b/src/lib/logger.rs @@ -32,17 +32,12 @@ pub(crate) struct LoggerOptions { } pub(crate) fn get_level(level_name: &str) -> LogLevel { - let mut level = LogLevel::INFO; - - if level_name == "verbose" { - level = LogLevel::VERBOSE; - } else if level_name == "error" { - level = LogLevel::ERROR; - } else if level_name == "off" { - level = LogLevel::OFF; + match level_name { + "verbose" => LogLevel::VERBOSE, + "error" => LogLevel::ERROR, + "off" => LogLevel::OFF, + _ => LogLevel::INFO } - - level } /// Returns the current logger level name diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 917a0cba..3d8ba9dd 100755 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -34,9 +34,11 @@ //! [Apache 2](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) open source license. //! +use either::Either; // Dependencies used in the binary `makers`: #[cfg(windows)] use nu_ansi_term as _; +use crate::types::CliArgs; #[macro_use] extern crate log; @@ -76,6 +78,6 @@ mod toolchain; mod version; /// Handles the command line arguments and executes the runner. -pub fn run_cli(command_name: String, sub_command: bool) { +pub fn run_cli(command_name: String, sub_command: bool) -> Either { cli::run_cli(command_name, sub_command) } From 38780a3ec222393b20ba82b1f3ea694587b114d9 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:15:31 -0400 Subject: [PATCH 04/21] [src/lib/*.rs] Fix tests broken by previous commit ; `rustfmt` --- src/lib/cli.rs | 13 ++- src/lib/cli_parser.rs | 18 +++-- src/lib/cli_parser_test.rs | 162 +++++++++++++++++++++++++++---------- src/lib/cli_test.rs | 20 +++-- src/lib/logger.rs | 2 +- src/lib/mod.rs | 2 +- 6 files changed, 160 insertions(+), 57 deletions(-) diff --git a/src/lib/cli.rs b/src/lib/cli.rs index 9fed804d..e460a214 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -21,8 +21,8 @@ use crate::time_summary; use crate::toolchain; use crate::types::{CliArgs, GlobalConfig}; use crate::version; +use either::{try_left, Either}; use std::time::SystemTime; -use either::{Either, try_left}; pub(crate) static VERSION: &str = env!("CARGO_PKG_VERSION"); pub(crate) static AUTHOR: &str = env!("CARGO_PKG_AUTHORS"); @@ -32,7 +32,10 @@ pub(crate) static DEFAULT_LOG_LEVEL: &str = "info"; pub(crate) static DEFAULT_TASK_NAME: &str = "default"; pub(crate) static DEFAULT_OUTPUT_FORMAT: &str = "default"; -pub fn run(cli_args: CliArgs, global_config: &GlobalConfig) -> Either { +pub fn run( + cli_args: CliArgs, + global_config: &GlobalConfig, +) -> Either { let start_time = SystemTime::now(); recursion_level::increment(); @@ -175,7 +178,11 @@ pub fn run(cli_args: CliArgs, global_config: &GlobalConfig) -> Either Either { let global_config = config::load(); - let cli_args = try_left!(cli_parser::parse(&global_config, &command_name, sub_command)); + let cli_args = try_left!(cli_parser::parse( + &global_config, + &command_name, + sub_command + )); run(cli_args.clone(), &global_config); Either::Left(cli_args) diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index eafc2639..110b9150 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -17,7 +17,6 @@ use cliparser::types::{ CliSpecMetaInfo, PositionalArgument, }; - use either::Either; fn get_args( @@ -462,7 +461,7 @@ pub fn parse_args( global_config: &GlobalConfig, command_name: &str, sub_command: bool, - args: Option> + args: Option>, ) -> Either { let spec = create_cli(&global_config); @@ -477,20 +476,27 @@ pub fn parse_args( // generate help text let help_text = cliparser::help(&spec); println!("{}", help_text); - return Either::Right(std::process::ExitCode::from(std::process::ExitCode::SUCCESS)) + return Either::Right(std::process::ExitCode::from( + std::process::ExitCode::SUCCESS, + )); } else if cli_parsed.arguments.contains("version") { // generate version text let version_text = cliparser::version(&spec); println!("{}", version_text); - return Either::Right(std::process::ExitCode::SUCCESS) + return Either::Right(std::process::ExitCode::SUCCESS); } - return Either::Left(get_args(&cli_parsed, &global_config, command_name, sub_command)) + return Either::Left(get_args( + &cli_parsed, + &global_config, + command_name, + sub_command, + )); } Err(error) => { let help_text = cliparser::help(&spec); println!("{}\n{}", &error, help_text); - return Either::Right(std::process::ExitCode::FAILURE) + return Either::Right(std::process::ExitCode::FAILURE); } } } diff --git a/src/lib/cli_parser_test.rs b/src/lib/cli_parser_test.rs index 139232f1..b1de348d 100644 --- a/src/lib/cli_parser_test.rs +++ b/src/lib/cli_parser_test.rs @@ -74,27 +74,41 @@ fn parse_args_cargo_make() { } #[test] -#[should_panic] fn parse_args_help_long() { - default_parse_cli_args(vec!["--help"]); + assert_eq!( + format!("{:?}", std::process::ExitCode::SUCCESS), + format!( + "{:?}", + default_parse_cli_args(vec!["--help"]).right().unwrap() + ) + ); } #[test] -#[should_panic] fn parse_args_help_short() { - default_parse_cli_args(vec!["-h"]); + assert_eq!( + format!("{:?}", std::process::ExitCode::SUCCESS), + format!("{:?}", default_parse_cli_args(vec!["-h"]).right().unwrap()) + ); } #[test] -#[should_panic] fn parse_args_version_long() { - default_parse_cli_args(vec!["--version"]); + assert_eq!( + format!("{:?}", std::process::ExitCode::SUCCESS), + format!( + "{:?}", + default_parse_cli_args(vec!["--version"]).right().unwrap() + ) + ); } #[test] -#[should_panic] fn parse_args_version_short() { - default_parse_cli_args(vec!["-V"]); + assert_eq!( + format!("{:?}", std::process::ExitCode::SUCCESS), + format!("{:?}", default_parse_cli_args(vec!["-V"]).right().unwrap()) + ); } #[test] @@ -114,14 +128,18 @@ fn parse_args_makefile() { #[test] fn parse_args_task() { - let mut cli_args = default_parse_cli_args(vec!["--task", "sometask"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--task", "sometask"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.task = "sometask".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-t", "sometask"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["-t", "sometask"]) + .left() + .unwrap(); assert_cli_args(&cli_args, &expected); cli_args = default_parse_cli_args(vec!["sometask"]).left().unwrap(); @@ -131,17 +149,23 @@ fn parse_args_task() { #[test] fn parse_args_profile() { - let mut cli_args = default_parse_cli_args(vec!["--profile", "someprofile"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--profile", "someprofile"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.profile = Some("someprofile".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-p", "someprofile"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["-p", "someprofile"]) + .left() + .unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--profile", "someprofile", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--profile", "someprofile", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -149,7 +173,9 @@ fn parse_args_profile() { #[test] fn parse_args_cwd() { - let cli_args = default_parse_cli_args(vec!["--cwd", "./mydir/subdir/"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--cwd", "./mydir/subdir/"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.cwd = Some("./mydir/subdir/".to_string()); @@ -159,7 +185,9 @@ fn parse_args_cwd() { #[test] fn parse_args_no_workspace() { - let cli_args = default_parse_cli_args(vec!["--no-workspace"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--no-workspace"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_workspace = true; @@ -169,7 +197,9 @@ fn parse_args_no_workspace() { #[test] fn parse_args_allow_private() { - let cli_args = default_parse_cli_args(vec!["--allow-private"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--allow-private"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.allow_private = true; @@ -179,7 +209,9 @@ fn parse_args_allow_private() { #[test] fn parse_args_skip_init_end_tasks() { - let cli_args = default_parse_cli_args(vec!["--skip-init-end-tasks"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--skip-init-end-tasks"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.skip_init_end_tasks = true; @@ -189,14 +221,18 @@ fn parse_args_skip_init_end_tasks() { #[test] fn parse_args_skip_tasks() { - let mut cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.skip_tasks_pattern = Some("pre-.*".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -204,22 +240,30 @@ fn parse_args_skip_tasks() { #[test] fn parse_args_env_file() { - let mut cli_args = default_parse_cli_args(vec!["--env-file", "./.env"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--env-file", "./.env"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.env_file = Some("./.env".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file=./.env"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--env-file=./.env"]) + .left() + .unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file", "./.env", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--env-file", "./.env", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file=./.env", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--env-file=./.env", "taskname"]) + .left() + .unwrap(); assert_cli_args(&cli_args, &expected); } @@ -235,7 +279,9 @@ fn parse_args_env() { cli_args = default_parse_cli_args(vec!["-e", "K=V"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3"]) + .left() + .unwrap(); expected.env = Some(vec![ "K1=V1".to_string(), "K2=V2".to_string(), @@ -245,7 +291,9 @@ fn parse_args_env() { cli_args = default_parse_cli_args(vec![ "-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3", "taskname", - ]).left().unwrap(); + ]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -253,17 +301,23 @@ fn parse_args_env() { #[test] fn parse_args_loglevel() { - let mut cli_args = default_parse_cli_args(vec!["--loglevel", "verbose"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--loglevel", "verbose"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "verbose".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-l", "verbose"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["-l", "verbose"]) + .left() + .unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--loglevel", "verbose", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--loglevel", "verbose", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -304,7 +358,9 @@ fn parse_args_no_color() { #[test] fn parse_args_time_summary() { - let cli_args = default_parse_cli_args(vec!["--time-summary"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--time-summary"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.print_time_summary = true; @@ -314,7 +370,9 @@ fn parse_args_time_summary() { #[test] fn parse_args_experimental() { - let cli_args = default_parse_cli_args(vec!["--experimental"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--experimental"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.experimental = true; @@ -324,7 +382,9 @@ fn parse_args_experimental() { #[test] fn parse_args_disable_check_for_updates() { - let cli_args = default_parse_cli_args(vec!["--disable-check-for-updates"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--disable-check-for-updates"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_check_for_updates = true; @@ -334,14 +394,18 @@ fn parse_args_disable_check_for_updates() { #[test] fn parse_args_output_format() { - let mut cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.output_format = "autocomplete".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -349,14 +413,18 @@ fn parse_args_output_format() { #[test] fn parse_args_output_file() { - let mut cli_args = default_parse_cli_args(vec!["--output-file", "./out"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--output-file", "./out"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.output_file = Some("./out".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--output-file", "./out", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--output-file", "./out", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -364,7 +432,9 @@ fn parse_args_output_file() { #[test] fn parse_args_print_steps() { - let cli_args = default_parse_cli_args(vec!["--print-steps"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--print-steps"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.print_only = true; @@ -374,7 +444,9 @@ fn parse_args_print_steps() { #[test] fn parse_args_list_all_steps() { - let cli_args = default_parse_cli_args(vec!["--list-all-steps"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--list-all-steps"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.list_all_steps = true; @@ -384,14 +456,18 @@ fn parse_args_list_all_steps() { #[test] fn parse_args_list_category_steps() { - let mut cli_args = default_parse_cli_args(vec!["--list-category-steps", "build"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--list-category-steps", "build"]) + .left() + .unwrap(); let mut expected = default_parsed_cli_args(); expected.list_category_steps = Some("build".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--list-category-steps", "build", "taskname"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--list-category-steps", "build", "taskname"]) + .left() + .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -420,10 +496,14 @@ fn parse_args_task_cmd() { cli_args = default_parse_cli_args(vec!["--", "task1"]).left().unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["task1", "arg1", "arg2"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["task1", "arg1", "arg2"]) + .left() + .unwrap(); expected.arguments = Some(vec!["arg1".to_string(), "arg2".to_string()]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--", "task1", "arg1", "arg2"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--", "task1", "arg1", "arg2"]) + .left() + .unwrap(); assert_cli_args(&cli_args, &expected); } diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index 674afae9..0b5ae261 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -393,7 +393,6 @@ fn run_bad_subcommand() { let cli_args = cli_parser::parse_args(&global_config, &"make".to_string(), true, Some(vec!["bad"])); - assert_eq!( format!("{:?}", &cli_args.clone().right().unwrap()), format!("{:?}", std::process::ExitCode::FAILURE) @@ -425,7 +424,12 @@ fn run_valid() { ); assert_eq!( - format!("{:?}", run(cli_args.left().unwrap(), &global_config).right().unwrap()), + format!( + "{:?}", + run(cli_args.left().unwrap(), &global_config) + .right() + .unwrap() + ), format!("{:?}", std::process::ExitCode::FAILURE) ); } @@ -442,7 +446,9 @@ fn run_with_global_config() { &"make".to_string(), true, Some(vec!["cargo", "make"]), - ).left().unwrap(); + ) + .left() + .unwrap(); run(cli_args, &global_config); } @@ -466,7 +472,9 @@ fn run_log_level_override() { "error", "-v", ]), - ).left().unwrap(); + ) + .left() + .unwrap(); run(cli_args, &global_config); } @@ -493,7 +501,9 @@ fn run_set_env_values() { "-t", "empty", ]), - ).left().unwrap(); + ) + .left() + .unwrap(); envmnt::set("ENV1_TEST", "EMPTY"); envmnt::set("ENV2_TEST", "EMPTY"); diff --git a/src/lib/logger.rs b/src/lib/logger.rs index 9cd5be99..0c68ad98 100755 --- a/src/lib/logger.rs +++ b/src/lib/logger.rs @@ -36,7 +36,7 @@ pub(crate) fn get_level(level_name: &str) -> LogLevel { "verbose" => LogLevel::VERBOSE, "error" => LogLevel::ERROR, "off" => LogLevel::OFF, - _ => LogLevel::INFO + _ => LogLevel::INFO, } } diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 3d8ba9dd..e12397ed 100755 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -36,9 +36,9 @@ use either::Either; // Dependencies used in the binary `makers`: +use crate::types::CliArgs; #[cfg(windows)] use nu_ansi_term as _; -use crate::types::CliArgs; #[macro_use] extern crate log; From a5dd7c668079135a14aa60e2380f692dc75b9cb9 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:20:35 -0400 Subject: [PATCH 05/21] [src/{main,makers}.rs] Percolate exit code up --- src/main.rs | 6 ++++-- src/makers.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index dc7ae7d3..4eb6a67f 100755 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,9 @@ fn get_name() -> String { "make".to_string() } -fn main() { +fn main() -> std::process::ExitCode { let name = get_name(); - cli::run_cli(name, true); + cli::run_cli(name, true) + .right() + .unwrap_or(std::process::ExitCode::SUCCESS) } diff --git a/src/makers.rs b/src/makers.rs index f30621fd..7b6308c3 100644 --- a/src/makers.rs +++ b/src/makers.rs @@ -20,9 +20,11 @@ fn get_name() -> String { "makers".to_string() } -fn main() { +fn main() -> std::process::ExitCode { #[cfg(windows)] let _ = nu_ansi_term::enable_ansi_support(); let name = get_name(); - cli::run_cli(name, false); + cli::run_cli(name, false) + .right() + .unwrap_or(std::process::ExitCode::SUCCESS) } From 58fd745dce407c32806f5efc98b6d78c4ec38303 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Thu, 11 Jul 2024 23:27:37 -0400 Subject: [PATCH 06/21] [src/lib/types.rs] Implement helper `either_to_result` --- src/lib/types.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/types.rs b/src/lib/types.rs index 4582c09e..4bfd5f43 100755 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -10,6 +10,7 @@ mod types_test; use crate::legacy; use crate::plugin::types::Plugins; use ci_info::types::CiInfo; +use either::Either; use git_info::types::GitInfo; use indexmap::{IndexMap, IndexSet}; use regex::Regex; @@ -2451,3 +2452,10 @@ pub struct CommandSpec { /// The command args pub args: Option>, } + +pub fn either_to_result(either: Either) -> Result { + match either { + Either::Left(lhs) => Ok(lhs), + Either::Right(rhs) => Err(rhs), + } +} From 2a2e03f207333d598f690445d4fc3d304d918aac Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 12 Jul 2024 00:32:06 -0400 Subject: [PATCH 07/21] [src/lib/cli.rs] Change function definition of `run` and related functions with `&` to avoid `clone`s ; [src/lib/**.rs] Fix build with new function definitions --- docs/api/src/cli/cli.rs.html | 4 +-- src/lib/cli.rs | 8 ++--- src/lib/cli_commands/list_steps.rs | 4 +-- src/lib/cli_commands/list_steps_test.rs | 4 +-- src/lib/cli_commands/print_steps.rs | 2 +- src/lib/cli_commands/print_steps_test.rs | 6 ++-- src/lib/cli_test.rs | 46 ++++++++++++------------ 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/api/src/cli/cli.rs.html b/docs/api/src/cli/cli.rs.html index 97f426f8..69f3a013 100644 --- a/docs/api/src/cli/cli.rs.html +++ b/docs/api/src/cli/cli.rs.html @@ -210,7 +210,7 @@ pub(crate) static DEFAULT_TASK_NAME: &str = "default"; pub(crate) static DEFAULT_OUTPUT_FORMAT: &str = "default"; -fn run(cli_args: CliArgs, global_config: &GlobalConfig) { +fn run(&cli_args: CliArgs, global_config: &GlobalConfig) { let start_time = SystemTime::now(); recursion_level::increment(); @@ -354,6 +354,6 @@ let cli_args = cli_parser::parse(&global_config, &command_name, sub_command); - run(cli_args, &global_config); + run(&cli_args, &global_config); } \ No newline at end of file diff --git a/src/lib/cli.rs b/src/lib/cli.rs index e460a214..b743f26c 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -33,7 +33,7 @@ pub(crate) static DEFAULT_TASK_NAME: &str = "default"; pub(crate) static DEFAULT_OUTPUT_FORMAT: &str = "default"; pub fn run( - cli_args: CliArgs, + cli_args: &CliArgs, global_config: &GlobalConfig, ) -> Either { let start_time = SystemTime::now(); @@ -140,7 +140,7 @@ pub fn run( &config, &cli_args.output_format, &cli_args.output_file, - cli_args.list_category_steps, + &cli_args.list_category_steps, cli_args.hide_uninteresting, ); } else if cli_args.diff_execution_plan { @@ -158,7 +158,7 @@ pub fn run( &task, &cli_args.output_format, cli_args.disable_workspace, - cli_args.skip_tasks_pattern, + &cli_args.skip_tasks_pattern, &env_info.crate_info, ); } else { @@ -184,6 +184,6 @@ pub fn run_cli(command_name: String, sub_command: bool) -> Either, - category: Option, + category: &Option, hide_uninteresting: bool, ) { let output = create_list(&config, output_format, category, hide_uninteresting); @@ -35,7 +35,7 @@ pub fn run( pub(crate) fn create_list( config: &Config, output_format: &str, - category_filter: Option, + category_filter: &Option, hide_uninteresting: bool, ) -> String { // category -> actual_task -> description diff --git a/src/lib/cli_commands/list_steps_test.rs b/src/lib/cli_commands/list_steps_test.rs index 2400452b..63ea6060 100644 --- a/src/lib/cli_commands/list_steps_test.rs +++ b/src/lib/cli_commands/list_steps_test.rs @@ -19,7 +19,7 @@ fn check( &config, output_format, output_file, - category, + &category, hide_uninteresting, ); @@ -32,7 +32,7 @@ fn check( expect.assert_eq(&actual); } None => { - let actual = create_list(&config, output_format, category, hide_uninteresting); + let actual = create_list(&config, output_format, &category, hide_uninteresting); expect.assert_eq(&actual); } } diff --git a/src/lib/cli_commands/print_steps.rs b/src/lib/cli_commands/print_steps.rs index c4540af4..6f7eb098 100644 --- a/src/lib/cli_commands/print_steps.rs +++ b/src/lib/cli_commands/print_steps.rs @@ -66,7 +66,7 @@ pub fn print( task: &str, output_format: &str, disable_workspace: bool, - skip_tasks_pattern: Option, + skip_tasks_pattern: &Option, crateinfo: &CrateInfo, ) { let skip_tasks_pattern_regex = match skip_tasks_pattern { diff --git a/src/lib/cli_commands/print_steps_test.rs b/src/lib/cli_commands/print_steps_test.rs index 7ec991f3..8407dfcc 100644 --- a/src/lib/cli_commands/print_steps_test.rs +++ b/src/lib/cli_commands/print_steps_test.rs @@ -35,7 +35,7 @@ fn print_default_format() { config.tasks.insert("end".to_string(), Task::new()); config.tasks.insert("test".to_string(), Task::new()); - print(&config, "test", "default", false, None, &CrateInfo::new()); + print(&config, "test", "default", false, &None, &CrateInfo::new()); } #[test] @@ -53,7 +53,7 @@ fn print_task_not_found() { config.tasks.insert("init".to_string(), Task::new()); config.tasks.insert("end".to_string(), Task::new()); - print(&config, "test", "default", false, None, &CrateInfo::new()); + print(&config, "test", "default", false, &None, &CrateInfo::new()); } #[test] @@ -75,7 +75,7 @@ fn print_task_not_found_but_skipped() { "test", "default", false, - Some("test".to_string()), + &Some("test".to_string()), &CrateInfo::new(), ); } diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index 0b5ae261..49d109fc 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -9,7 +9,7 @@ fn run_makefile_not_found() { let global_config = GlobalConfig::new(); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("bad.toml".to_string()), task: "empty".to_string(), @@ -46,7 +46,7 @@ fn run_empty_task() { let global_config = GlobalConfig::new(); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: None, task: "empty".to_string(), @@ -83,7 +83,7 @@ fn print_empty_task() { let global_config = GlobalConfig::new(); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: None, task: "empty".to_string(), @@ -120,7 +120,7 @@ fn list_empty_task() { let global_config = GlobalConfig::new(); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: None, task: "empty".to_string(), @@ -157,7 +157,7 @@ fn run_file_and_task() { let global_config = GlobalConfig::new(); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("./examples/dependencies.toml".to_string()), task: "A".to_string(), @@ -197,7 +197,7 @@ fn run_cwd_with_file() { assert!(env::set_current_dir(&directory).is_ok()); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("./examples/dependencies.toml".to_string()), task: "A".to_string(), @@ -235,7 +235,7 @@ fn run_file_not_go_to_project_root() { global_config.search_project_root = Some(false); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("./examples/dependencies.toml".to_string()), task: "A".to_string(), @@ -273,7 +273,7 @@ fn run_cwd_go_to_project_root_current_dir() { global_config.search_project_root = Some(true); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("./examples/dependencies.toml".to_string()), task: "A".to_string(), @@ -314,7 +314,7 @@ fn run_cwd_go_to_project_root_child_dir() { assert!(env::set_current_dir(&directory).is_ok()); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("./examples/dependencies.toml".to_string()), task: "A".to_string(), @@ -355,7 +355,7 @@ fn run_cwd_task_not_found() { assert!(env::set_current_dir(&directory).is_ok()); run( - CliArgs { + &CliArgs { command: "cargo make".to_string(), build_file: Some("./dependencies.toml".to_string()), task: "A".to_string(), @@ -398,7 +398,7 @@ fn run_bad_subcommand() { format!("{:?}", std::process::ExitCode::FAILURE) ); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); } #[test] @@ -426,7 +426,7 @@ fn run_valid() { assert_eq!( format!( "{:?}", - run(cli_args.left().unwrap(), &global_config) + run(&cli_args.left().unwrap(), &global_config) .right() .unwrap() ), @@ -450,7 +450,7 @@ fn run_with_global_config() { .left() .unwrap(); - run(cli_args, &global_config); + run(&cli_args, &global_config); } #[test] @@ -476,7 +476,7 @@ fn run_log_level_override() { .left() .unwrap(); - run(cli_args, &global_config); + run(&cli_args, &global_config); } #[test] @@ -509,7 +509,7 @@ fn run_set_env_values() { envmnt::set("ENV2_TEST", "EMPTY"); envmnt::set("ENV3_TEST", "EMPTY"); - run(cli_args, &global_config); + run(&cli_args, &global_config); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2a=TEST2b"); @@ -539,7 +539,7 @@ fn run_set_env_via_file() { envmnt::set("ENV2_TEST", "EMPTY"); envmnt::set("ENV3_TEST", "EMPTY"); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2"); @@ -578,7 +578,7 @@ fn run_set_env_both() { envmnt::set("ENV5_TEST", "EMPTY"); envmnt::set("ENV6_TEST", "EMPTY"); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2"); @@ -614,7 +614,7 @@ fn run_print_only() { ]), ); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); } #[test] @@ -639,7 +639,7 @@ fn run_diff_steps() { ]), ); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); } #[test] @@ -659,7 +659,7 @@ fn run_protected_flow_example() { ]), ); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); } #[test] @@ -680,7 +680,7 @@ fn run_no_task_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), ""); } @@ -706,7 +706,7 @@ fn run_set_task_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), @@ -729,7 +729,7 @@ fn run_set_task_var_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(cli_args.left().unwrap(), &global_config); + run(&cli_args.left().unwrap(), &global_config); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), From 73546586959761168b806157bf9ea92586f77973 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 12 Jul 2024 19:42:59 -0400 Subject: [PATCH 08/21] Rewrite `panic!` to percolate `Result` throughout, including with new `CargoMakeError` --- Cargo.lock | 28 ++- Cargo.toml | 1 + src/lib/cli.rs | 36 ++-- src/lib/cli_commands/diff_steps.rs | 11 +- src/lib/cli_commands/diff_steps_test.rs | 14 +- src/lib/cli_commands/list_steps.rs | 21 +- src/lib/cli_commands/list_steps_test.rs | 6 +- src/lib/cli_commands/print_steps.rs | 7 +- src/lib/cli_commands/print_steps_test.rs | 7 +- src/lib/cli_parser.rs | 55 ++--- src/lib/cli_parser_test.rs | 192 +++++++----------- src/lib/cli_test.rs | 66 +++--- src/lib/command.rs | 32 +-- src/lib/command_test.rs | 39 ++-- src/lib/condition.rs | 18 +- src/lib/condition_test.rs | 62 +++--- src/lib/config.rs | 31 +-- src/lib/config_test.rs | 21 +- src/lib/descriptor/env.rs | 10 +- src/lib/descriptor/env_test.rs | 8 +- src/lib/descriptor/makefiles/mod_test.rs | 14 +- src/lib/descriptor/mod.rs | 33 ++- src/lib/descriptor/mod_test.rs | 20 +- src/lib/environment/mod.rs | 21 +- src/lib/environment/mod_test.rs | 18 +- src/lib/error.rs | 170 ++++++++++++++++ src/lib/execution_plan.rs | 148 ++++++++------ src/lib/execution_plan_test.rs | 84 +++++--- src/lib/installer/cargo_plugin_installer.rs | 25 ++- .../installer/cargo_plugin_installer_test.rs | 23 ++- src/lib/installer/crate_installer.rs | 12 +- src/lib/installer/crate_installer_test.rs | 16 +- src/lib/installer/mod.rs | 16 +- src/lib/installer/mod_test.rs | 42 ++-- src/lib/mod.rs | 5 +- .../sdk/cm_plugin_check_task_condition.rs | 5 +- .../sdk/cm_plugin_force_plugin_set_test.rs | 2 +- .../plugin/sdk/cm_plugin_run_custom_task.rs | 6 +- src/lib/plugin/sdk/cm_plugin_run_task.rs | 6 +- src/lib/runner.rs | 158 ++++++++------ src/lib/runner_test.rs | 99 +++++---- src/lib/scriptengine/duck_script/mod.rs | 9 +- src/lib/scriptengine/duck_script/mod_test.rs | 27 ++- .../duck_script/sdk/cm_run_task.rs | 14 +- src/lib/scriptengine/generic_script.rs | 13 +- src/lib/scriptengine/generic_script_test.rs | 18 +- src/lib/scriptengine/mod.rs | 13 +- src/lib/scriptengine/mod_test.rs | 36 ++-- src/lib/scriptengine/os_script.rs | 7 +- src/lib/scriptengine/os_script_test.rs | 9 +- src/lib/scriptengine/rsscript.rs | 24 ++- src/lib/scriptengine/rsscript_test.rs | 33 ++- src/lib/scriptengine/shebang_script.rs | 5 +- src/lib/scriptengine/shebang_script_test.rs | 6 +- src/lib/scriptengine/shell_to_batch.rs | 11 +- src/lib/scriptengine/shell_to_batch_test.rs | 7 +- src/lib/types.rs | 7 + src/main.rs | 11 +- src/makers.rs | 11 +- 59 files changed, 1112 insertions(+), 737 deletions(-) create mode 100644 src/lib/error.rs diff --git a/Cargo.lock b/Cargo.lock index afccbe98..c319f6ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -177,6 +177,7 @@ dependencies = [ "sha2", "shell2batch", "strip-ansi-escapes", + "strum_macros", "toml", ] @@ -407,7 +408,7 @@ dependencies = [ "fs_extra", "fsio", "glob", - "heck", + "heck 0.4.1", "home", "ignore", "java-properties", @@ -653,6 +654,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.3.9" @@ -1206,6 +1213,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + [[package]] name = "ryu" version = "1.0.18" @@ -1356,6 +1369,19 @@ dependencies = [ "vte", ] +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "suppaftp" version = "5.4.0" diff --git a/Cargo.toml b/Cargo.toml index 1742039a..e6f1b10d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -77,6 +77,7 @@ serde_json = "^1" sha2 = "^0.10" shell2batch = "^0.4.5" strip-ansi-escapes = "^0.2" +strum_macros = "0.26.4" toml = "^0.8" [dev-dependencies] diff --git a/src/lib/cli.rs b/src/lib/cli.rs index b743f26c..b4768fb2 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -12,6 +12,7 @@ use crate::cli_parser; use crate::config; use crate::descriptor; use crate::environment; +use crate::error::CargoMakeError; use crate::logger; use crate::logger::LoggerOptions; use crate::profile; @@ -21,7 +22,6 @@ use crate::time_summary; use crate::toolchain; use crate::types::{CliArgs, GlobalConfig}; use crate::version; -use either::{try_left, Either}; use std::time::SystemTime; pub(crate) static VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -32,10 +32,7 @@ pub(crate) static DEFAULT_LOG_LEVEL: &str = "info"; pub(crate) static DEFAULT_TASK_NAME: &str = "default"; pub(crate) static DEFAULT_OUTPUT_FORMAT: &str = "default"; -pub fn run( - cli_args: &CliArgs, - global_config: &GlobalConfig, -) -> Either { +pub fn run(cli_args: &CliArgs, global_config: &GlobalConfig) -> Result<(), CargoMakeError> { let start_time = SystemTime::now(); recursion_level::increment(); @@ -121,7 +118,7 @@ pub fn run( None => profile::set_additional(&vec![]), }; - let env_info = environment::setup_env(&cli_args, &config, &task, home, &mut time_summary_vec); + let env_info = environment::setup_env(&cli_args, &config, &task, home, &mut time_summary_vec)?; time_summary::add(&mut time_summary_vec, "[Setup Env]", step_time); let crate_name = envmnt::get_or("CARGO_MAKE_CRATE_NAME", ""); @@ -142,7 +139,7 @@ pub fn run( &cli_args.output_file, &cli_args.list_category_steps, cli_args.hide_uninteresting, - ); + ) } else if cli_args.diff_execution_plan { let default_config = descriptor::load_internal_descriptors(true, experimental, None); cli_commands::diff_steps::run( @@ -151,7 +148,7 @@ pub fn run( &task, &cli_args, &env_info.crate_info, - ); + ) } else if cli_args.print_only { cli_commands::print_steps::print( &config, @@ -160,7 +157,7 @@ pub fn run( cli_args.disable_workspace, &cli_args.skip_tasks_pattern, &env_info.crate_info, - ); + ) } else { runner::run( config, @@ -169,21 +166,18 @@ pub fn run( &cli_args, start_time, time_summary_vec, - ); - } - Either::Right(std::process::ExitCode::SUCCESS) + ) + }?; + + Ok(()) } /// Handles the command line arguments and executes the runner. -pub fn run_cli(command_name: String, sub_command: bool) -> Either { - let global_config = config::load(); +pub fn run_cli(command_name: String, sub_command: bool) -> Result { + let global_config = config::load()?; - let cli_args = try_left!(cli_parser::parse( - &global_config, - &command_name, - sub_command - )); + let cli_args = cli_parser::parse(&global_config, &command_name, sub_command)?; - run(&cli_args, &global_config); - Either::Left(cli_args) + run(&cli_args, &global_config)?; + Ok(cli_args) } diff --git a/src/lib/cli_commands/diff_steps.rs b/src/lib/cli_commands/diff_steps.rs index 01991bc9..ecf31d9e 100644 --- a/src/lib/cli_commands/diff_steps.rs +++ b/src/lib/cli_commands/diff_steps.rs @@ -8,6 +8,7 @@ mod diff_steps_test; use crate::command; +use crate::error::CargoMakeError; use crate::execution_plan::create as create_execution_plan; use crate::io::{create_file, delete_file}; use crate::types::{CliArgs, Config, CrateInfo, ExecutionPlan}; @@ -28,7 +29,7 @@ pub(crate) fn run( task: &str, cli_args: &CliArgs, crateinfo: &CrateInfo, -) { +) -> Result<(), CargoMakeError> { let skip_tasks_pattern = match cli_args.skip_tasks_pattern { Some(ref pattern) => match Regex::new(pattern) { Ok(reg) => Some(reg), @@ -48,7 +49,7 @@ pub(crate) fn run( true, false, &skip_tasks_pattern, - ); + )?; let external_execution_plan = create_execution_plan( external_config, @@ -58,7 +59,7 @@ pub(crate) fn run( true, false, &skip_tasks_pattern, - ); + )?; let internal_file = create_file( &move |file: &mut File| write_as_string(&internal_execution_plan, &file), @@ -80,10 +81,12 @@ pub(crate) fn run( external_file.to_string(), ]), false, - ); + )?; delete_file(&internal_file); delete_file(&external_file); info!("Done"); + + Ok(()) } diff --git a/src/lib/cli_commands/diff_steps_test.rs b/src/lib/cli_commands/diff_steps_test.rs index 83154cd1..a831c291 100644 --- a/src/lib/cli_commands/diff_steps_test.rs +++ b/src/lib/cli_commands/diff_steps_test.rs @@ -25,7 +25,8 @@ fn run_same() { "test", &CliArgs::new(), &CrateInfo::new(), - ); + ) + .unwrap(); } #[test] @@ -65,7 +66,8 @@ fn run_different() { "test", &CliArgs::new(), &CrateInfo::new(), - ); + ) + .unwrap(); } #[test] @@ -102,7 +104,7 @@ fn run_different_with_skip() { let mut cli_args = CliArgs::new(); cli_args.skip_tasks_pattern = Some("test".to_string()); - run(&config1, &config2, "test", &cli_args, &CrateInfo::new()); + run(&config1, &config2, "test", &cli_args, &CrateInfo::new()).unwrap(); } #[test] @@ -139,7 +141,8 @@ fn run_missing_task_in_first_config() { "test", &CliArgs::new(), &CrateInfo::new(), - ); + ) + .unwrap(); } #[test] @@ -176,5 +179,6 @@ fn run_missing_task_in_second_config() { "test", &CliArgs::new(), &CrateInfo::new(), - ); + ) + .unwrap(); } diff --git a/src/lib/cli_commands/list_steps.rs b/src/lib/cli_commands/list_steps.rs index 0dab8948..a6bf1347 100644 --- a/src/lib/cli_commands/list_steps.rs +++ b/src/lib/cli_commands/list_steps.rs @@ -8,6 +8,7 @@ #[path = "list_steps_test.rs"] mod list_steps_test; +use crate::error::CargoMakeError; use crate::execution_plan; use crate::io; use crate::types::{Config, DeprecationInfo}; @@ -19,8 +20,8 @@ pub fn run( output_file: &Option, category: &Option, hide_uninteresting: bool, -) { - let output = create_list(&config, output_format, category, hide_uninteresting); +) -> Result<(), CargoMakeError> { + let output = create_list(&config, output_format, category, hide_uninteresting)?; match output_file { Some(file) => { @@ -28,16 +29,16 @@ pub fn run( () } None => print!("{}", output), - } + }; + Ok(()) } -/// Panics if task does not exist. pub(crate) fn create_list( config: &Config, output_format: &str, category_filter: &Option, hide_uninteresting: bool, -) -> String { +) -> Result { // category -> actual_task -> description let mut categories: BTreeMap> = BTreeMap::new(); // actual_task -> aliases @@ -45,13 +46,9 @@ pub(crate) fn create_list( // iterate over all tasks to build categories and aliases for key in config.tasks.keys() { - let actual_task_name = - execution_plan::get_actual_task_name(&config, &key).unwrap_or_else(|| { - error!("Task {} not found", &key); - panic!("Task {} not found", &key); - }); + let actual_task_name = execution_plan::get_actual_task_name(&config, &key)?; - let task = execution_plan::get_normalized_task(&config, &actual_task_name, true); + let task = execution_plan::get_normalized_task(&config, &actual_task_name, true)?; let is_private = match task.private { Some(private) => private, @@ -190,5 +187,5 @@ pub(crate) fn create_list( } } - buffer + Ok(buffer) } diff --git a/src/lib/cli_commands/list_steps_test.rs b/src/lib/cli_commands/list_steps_test.rs index 63ea6060..1ddbb4a2 100644 --- a/src/lib/cli_commands/list_steps_test.rs +++ b/src/lib/cli_commands/list_steps_test.rs @@ -21,7 +21,8 @@ fn check( output_file, &category, hide_uninteresting, - ); + ) + .unwrap(); let mut path = PathBuf::new(); path.push(&file); @@ -32,7 +33,8 @@ fn check( expect.assert_eq(&actual); } None => { - let actual = create_list(&config, output_format, &category, hide_uninteresting); + let actual = + create_list(&config, output_format, &category, hide_uninteresting).unwrap(); expect.assert_eq(&actual); } } diff --git a/src/lib/cli_commands/print_steps.rs b/src/lib/cli_commands/print_steps.rs index 6f7eb098..3426356b 100644 --- a/src/lib/cli_commands/print_steps.rs +++ b/src/lib/cli_commands/print_steps.rs @@ -7,6 +7,7 @@ #[path = "print_steps_test.rs"] mod print_steps_test; +use crate::error::CargoMakeError; use crate::execution_plan::create as create_execution_plan; use crate::types::{Config, CrateInfo, ExecutionPlan}; use regex::Regex; @@ -68,7 +69,7 @@ pub fn print( disable_workspace: bool, skip_tasks_pattern: &Option, crateinfo: &CrateInfo, -) { +) -> Result<(), CargoMakeError> { let skip_tasks_pattern_regex = match skip_tasks_pattern { Some(ref pattern) => match Regex::new(pattern) { Ok(reg) => Some(reg), @@ -88,7 +89,7 @@ pub fn print( false, false, &skip_tasks_pattern_regex, - ); + )?; debug!("Created execution plan: {:#?}", &execution_plan); let print_format = get_format_type(&output_format); @@ -97,4 +98,6 @@ pub fn print( PrintFormat::ShortDescription => print_short_description(&execution_plan), PrintFormat::Default => print_default(&execution_plan), }; + + Ok(()) } diff --git a/src/lib/cli_commands/print_steps_test.rs b/src/lib/cli_commands/print_steps_test.rs index 8407dfcc..b36e8bcc 100644 --- a/src/lib/cli_commands/print_steps_test.rs +++ b/src/lib/cli_commands/print_steps_test.rs @@ -35,7 +35,7 @@ fn print_default_format() { config.tasks.insert("end".to_string(), Task::new()); config.tasks.insert("test".to_string(), Task::new()); - print(&config, "test", "default", false, &None, &CrateInfo::new()); + print(&config, "test", "default", false, &None, &CrateInfo::new()).unwrap(); } #[test] @@ -53,7 +53,7 @@ fn print_task_not_found() { config.tasks.insert("init".to_string(), Task::new()); config.tasks.insert("end".to_string(), Task::new()); - print(&config, "test", "default", false, &None, &CrateInfo::new()); + print(&config, "test", "default", false, &None, &CrateInfo::new()).unwrap(); } #[test] @@ -77,7 +77,8 @@ fn print_task_not_found_but_skipped() { false, &Some("test".to_string()), &CrateInfo::new(), - ); + ) + .unwrap(); } #[test] diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index 110b9150..dd4980b5 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -17,7 +17,7 @@ use cliparser::types::{ CliSpecMetaInfo, PositionalArgument, }; -use either::Either; +use crate::error::CargoMakeError; fn get_args( cli_parsed: &CliParsed, @@ -462,50 +462,39 @@ pub fn parse_args( command_name: &str, sub_command: bool, args: Option>, -) -> Either { +) -> Result { let spec = create_cli(&global_config); - let parse_result = match args { + let cli_parsed = match args { Some(args_vec) => cliparser::parse(&args_vec, &spec), None => cliparser::parse_process(&spec), - }; - - match parse_result { - Ok(cli_parsed) => { - if cli_parsed.arguments.contains("help") { - // generate help text - let help_text = cliparser::help(&spec); - println!("{}", help_text); - return Either::Right(std::process::ExitCode::from( - std::process::ExitCode::SUCCESS, - )); - } else if cli_parsed.arguments.contains("version") { - // generate version text - let version_text = cliparser::version(&spec); - println!("{}", version_text); - return Either::Right(std::process::ExitCode::SUCCESS); - } + }?; - return Either::Left(get_args( - &cli_parsed, - &global_config, - command_name, - sub_command, - )); - } - Err(error) => { - let help_text = cliparser::help(&spec); - println!("{}\n{}", &error, help_text); - return Either::Right(std::process::ExitCode::FAILURE); - } + if cli_parsed.arguments.contains("help") { + // generate help text + let help_text = cliparser::help(&spec); + println!("{}", help_text); + return Err(std::process::ExitCode::SUCCESS.into()); + } else if cli_parsed.arguments.contains("version") { + // generate version text + let version_text = cliparser::version(&spec); + println!("{}", version_text); + return Err(std::process::ExitCode::SUCCESS.into()); } + + return Ok(get_args( + &cli_parsed, + &global_config, + command_name, + sub_command, + )); } pub fn parse( global_config: &GlobalConfig, command_name: &str, sub_command: bool, -) -> Either { +) -> Result { parse_args(global_config, command_name, sub_command, None) } diff --git a/src/lib/cli_parser_test.rs b/src/lib/cli_parser_test.rs index b1de348d..1b64123b 100644 --- a/src/lib/cli_parser_test.rs +++ b/src/lib/cli_parser_test.rs @@ -1,6 +1,6 @@ use super::*; -fn default_parse_cli_args(mut args: Vec<&str>) -> Either { +fn default_parse_cli_args(mut args: Vec<&str>) -> Result { let global_config = GlobalConfig::new(); args.insert(0, "makers"); parse_args(&global_config, "makers", false, Some(args)) @@ -55,31 +55,34 @@ fn assert_cli_args(cli_args_ref1: &CliArgs, cli_args_ref2: &CliArgs) { #[test] fn parse_args_makers() { let global_config = GlobalConfig::new(); - let cli_args = parse_args(&global_config, "makers", false, Some(vec!["makers"])); + let cli_args = parse_args(&global_config, "makers", false, Some(vec!["makers"])).unwrap(); let expected = default_parsed_cli_args(); - assert_cli_args(&cli_args.left().unwrap(), &expected); + assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_cargo_make() { let global_config = GlobalConfig::new(); - let cli_args = parse_args(&global_config, "make", true, Some(vec!["cargo", "make"])); + let cli_args = parse_args(&global_config, "make", true, Some(vec!["cargo", "make"])).unwrap(); let mut expected = default_parsed_cli_args(); expected.command = "cargo make".to_string(); - assert_cli_args(&cli_args.left().unwrap(), &expected); + assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_help_long() { assert_eq!( - format!("{:?}", std::process::ExitCode::SUCCESS), format!( "{:?}", - default_parse_cli_args(vec!["--help"]).right().unwrap() + CargoMakeError::ExitCode(std::process::ExitCode::SUCCESS) + ), + format!( + "{:?}", + default_parse_cli_args(vec!["--help"]).err().unwrap() ) ); } @@ -87,18 +90,24 @@ fn parse_args_help_long() { #[test] fn parse_args_help_short() { assert_eq!( - format!("{:?}", std::process::ExitCode::SUCCESS), - format!("{:?}", default_parse_cli_args(vec!["-h"]).right().unwrap()) + format!( + "{:?}", + CargoMakeError::ExitCode(std::process::ExitCode::SUCCESS) + ), + format!("{:?}", default_parse_cli_args(vec!["-h"]).err().unwrap()) ); } #[test] fn parse_args_version_long() { assert_eq!( - format!("{:?}", std::process::ExitCode::SUCCESS), format!( "{:?}", - default_parse_cli_args(vec!["--version"]).right().unwrap() + CargoMakeError::ExitCode(std::process::ExitCode::SUCCESS) + ), + format!( + "{:?}", + default_parse_cli_args(vec!["--version"]).err().unwrap() ) ); } @@ -106,8 +115,11 @@ fn parse_args_version_long() { #[test] fn parse_args_version_short() { assert_eq!( - format!("{:?}", std::process::ExitCode::SUCCESS), - format!("{:?}", default_parse_cli_args(vec!["-V"]).right().unwrap()) + format!( + "{:?}", + CargoMakeError::ExitCode(std::process::ExitCode::SUCCESS) + ), + format!("{:?}", default_parse_cli_args(vec!["-V"]).err().unwrap()) ); } @@ -118,54 +130,44 @@ fn parse_args_makefile() { let mut expected = default_parsed_cli_args(); expected.build_file = Some("./mymakefile.toml".to_string()); - assert_cli_args(&cli_args.left().unwrap(), &expected); + assert_cli_args(&cli_args.unwrap(), &expected); cli_args = default_parse_cli_args(vec!["--makefile", "./mymakefile.toml", "taskname"]); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); - assert_cli_args(&cli_args.left().unwrap(), &expected); + assert_cli_args(&cli_args.unwrap(), &expected); } #[test] fn parse_args_task() { - let mut cli_args = default_parse_cli_args(vec!["--task", "sometask"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--task", "sometask"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.task = "sometask".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-t", "sometask"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["-t", "sometask"]).unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["sometask"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["sometask"]).unwrap(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_profile() { - let mut cli_args = default_parse_cli_args(vec!["--profile", "someprofile"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--profile", "someprofile"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.profile = Some("someprofile".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-p", "someprofile"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["-p", "someprofile"]).unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--profile", "someprofile", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--profile", "someprofile", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -173,9 +175,7 @@ fn parse_args_profile() { #[test] fn parse_args_cwd() { - let cli_args = default_parse_cli_args(vec!["--cwd", "./mydir/subdir/"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--cwd", "./mydir/subdir/"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.cwd = Some("./mydir/subdir/".to_string()); @@ -185,9 +185,7 @@ fn parse_args_cwd() { #[test] fn parse_args_no_workspace() { - let cli_args = default_parse_cli_args(vec!["--no-workspace"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--no-workspace"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_workspace = true; @@ -197,9 +195,7 @@ fn parse_args_no_workspace() { #[test] fn parse_args_allow_private() { - let cli_args = default_parse_cli_args(vec!["--allow-private"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--allow-private"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.allow_private = true; @@ -209,9 +205,7 @@ fn parse_args_allow_private() { #[test] fn parse_args_skip_init_end_tasks() { - let cli_args = default_parse_cli_args(vec!["--skip-init-end-tasks"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--skip-init-end-tasks"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.skip_init_end_tasks = true; @@ -221,18 +215,14 @@ fn parse_args_skip_init_end_tasks() { #[test] fn parse_args_skip_tasks() { - let mut cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.skip_tasks_pattern = Some("pre-.*".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--skip-tasks", "pre-.*", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -240,48 +230,39 @@ fn parse_args_skip_tasks() { #[test] fn parse_args_env_file() { - let mut cli_args = default_parse_cli_args(vec!["--env-file", "./.env"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--env-file", "./.env"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.env_file = Some("./.env".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file=./.env"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--env-file=./.env"]).unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file", "./.env", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--env-file", "./.env", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--env-file=./.env", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--env-file=./.env", "taskname"]).unwrap(); assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_env() { - let mut cli_args = default_parse_cli_args(vec!["--env", "K=V"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--env", "K=V"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.env = Some(vec!["K=V".to_string()]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-e", "K=V"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["-e", "K=V"]).unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3"]) - .left() - .unwrap(); + cli_args = + default_parse_cli_args(vec!["-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3"]).unwrap(); expected.env = Some(vec![ "K1=V1".to_string(), "K2=V2".to_string(), @@ -292,7 +273,6 @@ fn parse_args_env() { cli_args = default_parse_cli_args(vec![ "-e", "K1=V1", "-e", "K2=V2", "--env", "K3=V3", "taskname", ]) - .left() .unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); @@ -301,23 +281,17 @@ fn parse_args_env() { #[test] fn parse_args_loglevel() { - let mut cli_args = default_parse_cli_args(vec!["--loglevel", "verbose"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--loglevel", "verbose"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "verbose".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-l", "verbose"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["-l", "verbose"]).unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--loglevel", "verbose", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--loglevel", "verbose", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -325,20 +299,20 @@ fn parse_args_loglevel() { #[test] fn parse_args_verbose() { - let mut cli_args = default_parse_cli_args(vec!["--verbose"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--verbose"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "verbose".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["-v"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["-v"]).unwrap(); assert_cli_args(&cli_args, &expected); } #[test] fn parse_args_quiet() { - let cli_args = default_parse_cli_args(vec!["--quiet"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--quiet"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.log_level = "error".to_string(); @@ -348,7 +322,7 @@ fn parse_args_quiet() { #[test] fn parse_args_no_color() { - let cli_args = default_parse_cli_args(vec!["--no-color"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--no-color"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_color = true; @@ -358,9 +332,7 @@ fn parse_args_no_color() { #[test] fn parse_args_time_summary() { - let cli_args = default_parse_cli_args(vec!["--time-summary"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--time-summary"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.print_time_summary = true; @@ -370,9 +342,7 @@ fn parse_args_time_summary() { #[test] fn parse_args_experimental() { - let cli_args = default_parse_cli_args(vec!["--experimental"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--experimental"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.experimental = true; @@ -382,9 +352,7 @@ fn parse_args_experimental() { #[test] fn parse_args_disable_check_for_updates() { - let cli_args = default_parse_cli_args(vec!["--disable-check-for-updates"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--disable-check-for-updates"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.disable_check_for_updates = true; @@ -394,18 +362,14 @@ fn parse_args_disable_check_for_updates() { #[test] fn parse_args_output_format() { - let mut cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.output_format = "autocomplete".to_string(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--output-format", "autocomplete", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -413,18 +377,14 @@ fn parse_args_output_format() { #[test] fn parse_args_output_file() { - let mut cli_args = default_parse_cli_args(vec!["--output-file", "./out"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--output-file", "./out"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.output_file = Some("./out".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--output-file", "./out", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--output-file", "./out", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -432,9 +392,7 @@ fn parse_args_output_file() { #[test] fn parse_args_print_steps() { - let cli_args = default_parse_cli_args(vec!["--print-steps"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--print-steps"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.print_only = true; @@ -444,9 +402,7 @@ fn parse_args_print_steps() { #[test] fn parse_args_list_all_steps() { - let cli_args = default_parse_cli_args(vec!["--list-all-steps"]) - .left() - .unwrap(); + let cli_args = default_parse_cli_args(vec!["--list-all-steps"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.list_all_steps = true; @@ -456,18 +412,14 @@ fn parse_args_list_all_steps() { #[test] fn parse_args_list_category_steps() { - let mut cli_args = default_parse_cli_args(vec!["--list-category-steps", "build"]) - .left() - .unwrap(); + let mut cli_args = default_parse_cli_args(vec!["--list-category-steps", "build"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.list_category_steps = Some("build".to_string()); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--list-category-steps", "build", "taskname"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--list-category-steps", "build", "taskname"]).unwrap(); expected.task = "taskname".to_string(); expected.arguments = Some(vec![]); assert_cli_args(&cli_args, &expected); @@ -475,7 +427,7 @@ fn parse_args_list_category_steps() { #[test] fn parse_args_diff_steps() { - let cli_args = default_parse_cli_args(vec!["--diff-steps"]).left().unwrap(); + let cli_args = default_parse_cli_args(vec!["--diff-steps"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.diff_execution_plan = true; @@ -485,7 +437,7 @@ fn parse_args_diff_steps() { #[test] fn parse_args_task_cmd() { - let mut cli_args = default_parse_cli_args(vec!["task1"]).left().unwrap(); + let mut cli_args = default_parse_cli_args(vec!["task1"]).unwrap(); let mut expected = default_parsed_cli_args(); expected.task = "task1".to_string(); @@ -493,17 +445,13 @@ fn parse_args_task_cmd() { assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--", "task1"]).left().unwrap(); + cli_args = default_parse_cli_args(vec!["--", "task1"]).unwrap(); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["task1", "arg1", "arg2"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["task1", "arg1", "arg2"]).unwrap(); expected.arguments = Some(vec!["arg1".to_string(), "arg2".to_string()]); assert_cli_args(&cli_args, &expected); - cli_args = default_parse_cli_args(vec!["--", "task1", "arg1", "arg2"]) - .left() - .unwrap(); + cli_args = default_parse_cli_args(vec!["--", "task1", "arg1", "arg2"]).unwrap(); assert_cli_args(&cli_args, &expected); } diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index 49d109fc..18c3c4b7 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -37,7 +37,8 @@ fn run_makefile_not_found() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -74,7 +75,8 @@ fn run_empty_task() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -111,7 +113,8 @@ fn print_empty_task() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -148,7 +151,8 @@ fn list_empty_task() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -185,7 +189,8 @@ fn run_file_and_task() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -225,7 +230,8 @@ fn run_cwd_with_file() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -263,7 +269,8 @@ fn run_file_not_go_to_project_root() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -301,7 +308,8 @@ fn run_cwd_go_to_project_root_current_dir() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -342,7 +350,8 @@ fn run_cwd_go_to_project_root_child_dir() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] @@ -383,22 +392,22 @@ fn run_cwd_task_not_found() { hide_uninteresting: false, }, &global_config, - ); + ) + .unwrap(); } #[test] -#[should_panic] fn run_bad_subcommand() { let global_config = GlobalConfig::new(); let cli_args = cli_parser::parse_args(&global_config, &"make".to_string(), true, Some(vec!["bad"])); assert_eq!( - format!("{:?}", &cli_args.clone().right().unwrap()), - format!("{:?}", std::process::ExitCode::FAILURE) + format!("{:?}", &cli_args.err().unwrap()), + "ParserError { error: InvalidCommandLine(\"Command does not match spec, command line: [\\\"bad\\\"]\") }" ); - run(&cli_args.left().unwrap(), &global_config); + // run(&cli_args.unwrap(), &global_config).unwrap(); } #[test] @@ -426,9 +435,7 @@ fn run_valid() { assert_eq!( format!( "{:?}", - run(&cli_args.left().unwrap(), &global_config) - .right() - .unwrap() + run(&cli_args.unwrap(), &global_config).err().unwrap() ), format!("{:?}", std::process::ExitCode::FAILURE) ); @@ -447,10 +454,9 @@ fn run_with_global_config() { true, Some(vec!["cargo", "make"]), ) - .left() .unwrap(); - run(&cli_args, &global_config); + run(&cli_args, &global_config).unwrap(); } #[test] @@ -473,10 +479,9 @@ fn run_log_level_override() { "-v", ]), ) - .left() .unwrap(); - run(&cli_args, &global_config); + run(&cli_args, &global_config).unwrap(); } #[test] @@ -502,14 +507,13 @@ fn run_set_env_values() { "empty", ]), ) - .left() .unwrap(); envmnt::set("ENV1_TEST", "EMPTY"); envmnt::set("ENV2_TEST", "EMPTY"); envmnt::set("ENV3_TEST", "EMPTY"); - run(&cli_args, &global_config); + run(&cli_args, &global_config).unwrap(); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2a=TEST2b"); @@ -539,7 +543,7 @@ fn run_set_env_via_file() { envmnt::set("ENV2_TEST", "EMPTY"); envmnt::set("ENV3_TEST", "EMPTY"); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2"); @@ -578,7 +582,7 @@ fn run_set_env_both() { envmnt::set("ENV5_TEST", "EMPTY"); envmnt::set("ENV6_TEST", "EMPTY"); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); assert_eq!(envmnt::get_or_panic("ENV1_TEST"), "TEST1"); assert_eq!(envmnt::get_or_panic("ENV2_TEST"), "TEST2"); @@ -614,7 +618,7 @@ fn run_print_only() { ]), ); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); } #[test] @@ -639,7 +643,7 @@ fn run_diff_steps() { ]), ); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); } #[test] @@ -659,7 +663,7 @@ fn run_protected_flow_example() { ]), ); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); } #[test] @@ -680,7 +684,7 @@ fn run_no_task_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), ""); } @@ -706,7 +710,7 @@ fn run_set_task_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), @@ -729,7 +733,7 @@ fn run_set_task_var_args() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(&cli_args.left().unwrap(), &global_config); + run(&cli_args.unwrap(), &global_config).unwrap(); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), diff --git a/src/lib/command.rs b/src/lib/command.rs index b59b338e..0746a6d9 100755 --- a/src/lib/command.rs +++ b/src/lib/command.rs @@ -7,6 +7,7 @@ #[path = "command_test.rs"] mod command_test; +use crate::error::CargoMakeError; use crate::logger; use crate::toolchain; use crate::types::{CommandSpec, Step, UnstableFeature}; @@ -53,12 +54,14 @@ pub(crate) fn get_exit_code_from_output(output: &io::Result, force: bool } } -/// Validates the exit code code and if not 0 or unable to validate it, panic. -pub(crate) fn validate_exit_code(code: i32) { +/// Validates the exit code and if not 0 or unable to validate it, err +pub(crate) fn validate_exit_code(code: i32) -> Result<(), CargoMakeError> { if code == -1 { - error!("Error while executing command, unable to extract exit code."); + Err(CargoMakeError::ExitCodeValidation) } else if code != 0 { - error!("Error while executing command, exit code: {}", code); + Err(CargoMakeError::ExitCodeError(code)) + } else { + Ok(()) } } @@ -145,7 +148,7 @@ pub(crate) fn run_script_get_exit_code( script_runner: Option, cli_arguments: &Vec, validate: bool, -) -> i32 { +) -> Result { let output = run_script_get_output(&script_lines, script_runner, cli_arguments, false, None); let exit_code = match output { @@ -154,10 +157,10 @@ pub(crate) fn run_script_get_exit_code( }; if validate { - validate_exit_code(exit_code); + validate_exit_code(exit_code)?; } - exit_code + Ok(exit_code) } /// Runs the requested command and return its output. @@ -259,16 +262,20 @@ fn spawn_command(mut command: Command) -> io::Result { } /// Runs the requested command and panics in case of any error. -pub(crate) fn run_command(command_string: &str, args: &Option>, validate: bool) -> i32 { +pub(crate) fn run_command( + command_string: &str, + args: &Option>, + validate: bool, +) -> Result { let output = run_command_get_output(&command_string, &args, false); let exit_code = get_exit_code_from_output(&output, !validate); if validate { - validate_exit_code(exit_code); + validate_exit_code(exit_code)?; } - exit_code + Ok(exit_code) } /// Runs the requested command and returns the stdout if exit code is valid. @@ -294,7 +301,7 @@ pub(crate) fn run_command_get_output_string( } /// Runs the given task command. -pub(crate) fn run(step: &Step) { +pub(crate) fn run(step: &Step) -> Result<(), CargoMakeError> { let validate = !step.config.should_ignore_errors(); match step.config.command { @@ -309,8 +316,9 @@ pub(crate) fn run(step: &Step) { }, }; - run_command(&command_spec.command, &command_spec.args, validate); + run_command(&command_spec.command, &command_spec.args, validate)?; } None => debug!("No command defined."), }; + Ok(()) } diff --git a/src/lib/command_test.rs b/src/lib/command_test.rs index c0fc0df7..f3418eb3 100755 --- a/src/lib/command_test.rs +++ b/src/lib/command_test.rs @@ -3,20 +3,24 @@ use crate::test; use crate::types::Task; #[test] -#[should_panic] fn validate_exit_code_unable_to_fetch() { - validate_exit_code(-1); + assert_eq!( + format!("{:?}", validate_exit_code(-1).err().unwrap()), + format!("{:?}", CargoMakeError::ExitCodeValidation) + ); } #[test] -#[should_panic] fn validate_exit_code_not_zero() { - validate_exit_code(1); + assert_eq!( + format!("{:?}", validate_exit_code(1).err().unwrap()), + format!("{:?}", CargoMakeError::ExitCodeError(1)) + ); } #[test] fn validate_exit_code_zero() { - validate_exit_code(0); + validate_exit_code(0).unwrap(); } #[test] @@ -84,7 +88,7 @@ fn run_no_command() { config: task, }; - run(&step); + run(&step).unwrap(); } #[test] @@ -98,7 +102,7 @@ fn run_command() { config: task, }; - run(&step); + run(&step).unwrap(); } #[test] @@ -116,7 +120,7 @@ fn run_command_for_toolchain() { config: task, }; - run(&step); + run(&step).unwrap(); } } @@ -133,7 +137,7 @@ fn run_command_error() { config: task, }; - run(&step); + run(&step).unwrap(); } #[test] @@ -147,23 +151,23 @@ fn run_command_error_ignore_errors() { config: task, }; - run(&step); + run(&step).unwrap(); } #[test] fn run_script_get_exit_code_valid() { - run_script_get_exit_code(&vec!["echo 1".to_string()], None, &vec![], true); + run_script_get_exit_code(&vec!["echo 1".to_string()], None, &vec![], true).unwrap(); } #[test] #[should_panic] fn run_script_get_exit_code_error() { - run_script_get_exit_code(&vec!["exit 1".to_string()], None, &vec![], true); + run_script_get_exit_code(&vec!["exit 1".to_string()], None, &vec![], true).unwrap(); } #[test] fn run_script_get_exit_code_error_force() { - run_script_get_exit_code(&vec!["exit 1".to_string()], None, &vec![], false); + run_script_get_exit_code(&vec!["exit 1".to_string()], None, &vec![], false).unwrap(); } #[test] @@ -174,7 +178,8 @@ fn run_script_get_exit_code_custom_runner() { Some("bash".to_string()), &vec![], true, - ); + ) + .unwrap(); } #[test] @@ -185,7 +190,8 @@ fn run_script_get_exit_code_cli_args_valid() { None, &vec!["0".to_string()], true, - ); + ) + .unwrap(); } #[test] @@ -197,5 +203,6 @@ fn run_script_get_exit_code_cli_args_error() { None, &vec!["1".to_string()], true, - ); + ) + .unwrap(); } diff --git a/src/lib/condition.rs b/src/lib/condition.rs index e002b725..4b044582 100755 --- a/src/lib/condition.rs +++ b/src/lib/condition.rs @@ -8,6 +8,7 @@ mod condition_test; use crate::environment; +use crate::error::CargoMakeError; use crate::profile; use crate::scriptengine; use crate::types; @@ -599,7 +600,7 @@ fn validate_script( condition_script: &Option, script_runner: Option, script_runner_args: Option>, -) -> bool { +) -> Result { match condition_script { Some(ref script) => { debug!("Checking task condition script."); @@ -614,7 +615,7 @@ fn validate_script( &vec![], ); } - None => true, + None => Ok(true), } } @@ -628,7 +629,7 @@ pub(crate) fn validate_conditions( condition_script: &Option, script_runner: Option, script_runner_args: Option>, -) -> bool { +) -> Result { let condition_type = match condition { Some(ref value) => value.get_condition_type(), None => ConditionType::And, @@ -636,19 +637,22 @@ pub(crate) fn validate_conditions( let criteria_passed = validate_criteria(Some(&flow_info), &condition); if !criteria_passed && condition_type == ConditionType::And { - false + Ok(false) } else if criteria_passed && condition.is_some() && condition_type != ConditionType::And { - true + Ok(true) } else { if condition_script.is_none() && !criteria_passed { - false + Ok(false) } else { validate_script(&condition_script, script_runner, script_runner_args) } } } -pub(crate) fn validate_condition_for_step(flow_info: &FlowInfo, step: &Step) -> bool { +pub(crate) fn validate_condition_for_step( + flow_info: &FlowInfo, + step: &Step, +) -> Result { validate_conditions( &flow_info, &step.config.condition, diff --git a/src/lib/condition_test.rs b/src/lib/condition_test.rs index 23f69c24..ea20f95c 100755 --- a/src/lib/condition_test.rs +++ b/src/lib/condition_test.rs @@ -1730,7 +1730,7 @@ fn validate_env_contains_invalid_partial_found_with_any() { #[test] fn validate_script_empty() { - let enabled = validate_script(&None, None, None); + let enabled = validate_script(&None, None, None).unwrap(); assert!(enabled); } @@ -1741,7 +1741,8 @@ fn validate_script_valid() { &Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])), None, None, - ); + ) + .unwrap(); assert!(enabled); } @@ -1752,7 +1753,8 @@ fn validate_script_invalid() { &Some(ConditionScriptValue::Text(vec!["exit 1".to_string()])), None, None, - ); + ) + .unwrap(); assert!(!enabled); } @@ -1765,7 +1767,8 @@ fn validate_script_valid_with_duckscript_shebang() { ])), None, None, - ); + ) + .unwrap(); assert!(enabled); } @@ -1778,7 +1781,8 @@ fn validate_script_invalid_with_duckscript_shebang() { ])), None, None, - ); + ) + .unwrap(); assert!(!enabled); } @@ -3532,7 +3536,7 @@ fn validate_condition_for_step_both_valid() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -3593,7 +3597,7 @@ fn validate_condition_for_step_valid_script_invalid() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 1".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -3654,7 +3658,7 @@ fn validate_condition_for_step_valid_script_invalid_or() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 1".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -3711,7 +3715,7 @@ fn validate_condition_for_step_invalid_script_valid() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -3769,7 +3773,7 @@ fn validate_condition_for_step_invalid_env_set() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -3829,7 +3833,7 @@ fn validate_condition_for_step_invalid_env_not_set() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -3894,7 +3898,7 @@ fn validate_condition_for_step_valid_env() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -3956,7 +3960,7 @@ fn validate_condition_for_step_invalid_env_not_found() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4021,7 +4025,7 @@ fn validate_condition_for_step_invalid_env_not_equal() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4086,7 +4090,7 @@ fn validate_condition_for_step_valid_env_contains_same() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4151,7 +4155,7 @@ fn validate_condition_for_step_valid_env_contains() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4213,7 +4217,7 @@ fn validate_condition_for_step_invalid_env_contains_not_found() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4278,7 +4282,7 @@ fn validate_condition_for_step_invalid_env_contains_not_contains() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4341,7 +4345,7 @@ fn validate_condition_for_step_valid_rust_version() { files_modified: None, }); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4405,7 +4409,7 @@ fn validate_condition_for_step_invalid_rust_version() { files_modified: None, }); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4466,7 +4470,7 @@ fn validate_condition_for_step_both_valid_and() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4530,7 +4534,7 @@ fn validate_condition_for_step_value_partial_valid_and() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4591,7 +4595,7 @@ fn validate_condition_for_step_group_partial_valid_and() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } @@ -4652,7 +4656,7 @@ fn validate_condition_for_step_both_valid_or() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4716,7 +4720,7 @@ fn validate_condition_for_step_value_partial_valid_or() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4777,7 +4781,7 @@ fn validate_condition_for_step_group_partial_valid_or() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4838,7 +4842,7 @@ fn validate_condition_for_step_both_valid_group_or() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4902,7 +4906,7 @@ fn validate_condition_for_step_value_partial_valid_group_or() { }); step.config.condition_script = Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(enabled); } @@ -4961,7 +4965,7 @@ fn validate_condition_for_step_group_partial_valid_group_or() { files_modified: None, }); - let enabled = validate_condition_for_step(&flow_info, &step); + let enabled = validate_condition_for_step(&flow_info, &step).unwrap(); assert!(!enabled); } diff --git a/src/lib/config.rs b/src/lib/config.rs index ea1a1957..dbd3967b 100644 --- a/src/lib/config.rs +++ b/src/lib/config.rs @@ -7,6 +7,7 @@ #[path = "config_test.rs"] mod config_test; +use crate::error::CargoMakeError; use crate::storage; use crate::types::GlobalConfig; use fsio::file::read_text_file; @@ -20,36 +21,26 @@ pub fn get_config_directory() -> Option { storage::get_storage_directory(os_directory, CONFIG_FILE, true) } -pub fn load_from_path(directory: PathBuf) -> GlobalConfig { +pub fn load_from_path(directory: PathBuf) -> Result { let file_path = Path::new(&directory).join(CONFIG_FILE); debug!("Loading config from: {:#?}", &file_path); if file_path.exists() { - match read_text_file(&file_path) { - Ok(config_str) => { - let mut global_config: GlobalConfig = match toml::from_str(&config_str) { - Ok(value) => value, - Err(error) => panic!("Unable to parse global configuration file, {}", error), - }; - - global_config.file_name = Some(FromPath::from_path(&file_path)); - - global_config - } - Err(error) => panic!( - "Unable to read config file: {:?} error: {}", - &file_path, error - ), - } + let config_str = read_text_file(&file_path)?; + let mut global_config: GlobalConfig = toml::from_str(&config_str)?; + + global_config.file_name = Some(FromPath::from_path(&file_path)); + + Ok(global_config) } else { - GlobalConfig::new() + Ok(GlobalConfig::new()) } } /// Returns the configuration -pub fn load() -> GlobalConfig { +pub fn load() -> Result { match get_config_directory() { Some(directory) => load_from_path(directory), - None => GlobalConfig::new(), + None => Ok(GlobalConfig::new()), } } diff --git a/src/lib/config_test.rs b/src/lib/config_test.rs index c0c872d6..98fc7698 100644 --- a/src/lib/config_test.rs +++ b/src/lib/config_test.rs @@ -3,8 +3,8 @@ use std::env; #[test] fn load_from_path_exists() { - let path = PathBuf::from("examples/cargo-make"); - let global_config = load_from_path(path); + let path: PathBuf = ["examples", "cargo-make"].iter().collect(); + let global_config = load_from_path(path).unwrap(); assert!(global_config.file_name.is_some()); assert_eq!(global_config.log_level.unwrap(), "error".to_string()); @@ -21,8 +21,8 @@ fn load_from_path_exists() { #[test] fn load_from_path_not_exists() { - let path = PathBuf::from("examples2/.cargo-make"); - let global_config = load_from_path(path); + let path: PathBuf = ["examples2", ".cargo-make"].iter().collect(); + let global_config = load_from_path(path).unwrap(); assert!(global_config.file_name.is_none()); assert!(global_config.log_level.is_none()); @@ -34,10 +34,15 @@ fn load_from_path_not_exists() { #[test] #[ignore] fn load_with_cargo_home() { - let path = env::current_dir().unwrap(); - let directory = path.join("examples/cargo-make"); + let directory: PathBuf = [ + env::current_dir().unwrap(), + "examples".into(), + "cargo-make".into(), + ] + .iter() + .collect(); envmnt::set("CARGO_MAKE_HOME", directory.to_str().unwrap()); - let global_config = load(); + let global_config = load().unwrap(); assert!(global_config.file_name.is_some()); assert_eq!(global_config.log_level.unwrap(), "error".to_string()); @@ -56,7 +61,7 @@ fn load_with_cargo_home() { #[ignore] fn load_without_cargo_home() { envmnt::remove("CARGO_MAKE_HOME"); - let global_config = load(); + let global_config = load().unwrap(); assert!(global_config.search_project_root.is_some()); } diff --git a/src/lib/descriptor/env.rs b/src/lib/descriptor/env.rs index fdb10791..1c34f04d 100644 --- a/src/lib/descriptor/env.rs +++ b/src/lib/descriptor/env.rs @@ -1,3 +1,4 @@ +use crate::error::CargoMakeError; use crate::types::{ EnvFile, EnvValue, EnvValueConditioned, EnvValueDecode, EnvValuePathGlob, EnvValueScript, }; @@ -124,7 +125,7 @@ fn env_depends_on(val: &EnvValue) -> Vec<&str> { pub(crate) fn merge_env( base: &IndexMap, ext: &IndexMap, -) -> Result, String> { +) -> Result, CargoMakeError> { let combined = [base, ext]; let combined: Vec<_> = env_unique(&combined); @@ -161,9 +162,6 @@ pub(crate) fn merge_env( // (node) is reachable from every other node. // This means that there **must** be a cycle. // This isn't strictly necessary, but aids when debugging. - let mut err = - "A cycle between different env variables has been detected (E001, see: https://github.com/sagiegurari/cargo-make#e001 for more information)." - .to_owned(); for scc in kosaraju_scc(&graph) { let render = scc .iter() @@ -172,11 +170,11 @@ pub(crate) fn merge_env( .reduce(|acc, name| format!("{} -> {}", acc, name)); if let Some(render) = render { - err.push_str(&format!(" Cycle: {}.", render)); + return Err(CargoMakeError::EnvVarCycle(format!(" Cycle: {}.", render))); } } - return Err(err); + return Err(CargoMakeError::EnvVarCycle(String::new())); } }; diff --git a/src/lib/descriptor/env_test.rs b/src/lib/descriptor/env_test.rs index ee523811..4cb4ab90 100644 --- a/src/lib/descriptor/env_test.rs +++ b/src/lib/descriptor/env_test.rs @@ -162,7 +162,9 @@ fn merge_env_cycle() { let mut map2 = IndexMap::new(); map2.insert("env1".to_owned(), EnvValue::Value("${env2}".to_owned())); - let output = merge_env(&map1, &map2).expect_err("should have cycle"); + let output = merge_env(&map1, &map2) + .expect_err("should have cycle") + .to_string(); assert!(output.ends_with("env2 -> env1 -> env2.") || output.ends_with("env1 -> env2 -> env1.")); } @@ -173,7 +175,9 @@ fn merge_env_no_cycle_if_pointing_to_self_not_external() { map2.insert("test".to_string(), EnvValue::Value("${test}".to_string())); - let output = merge_env(&map1, &map2).expect_err("should have cycle"); + let output = merge_env(&map1, &map2) + .expect_err("should have cycle") + .to_string(); assert!(output.ends_with("test -> test.")); } diff --git a/src/lib/descriptor/makefiles/mod_test.rs b/src/lib/descriptor/makefiles/mod_test.rs index 6d45fce6..a4c950a9 100644 --- a/src/lib/descriptor/makefiles/mod_test.rs +++ b/src/lib/descriptor/makefiles/mod_test.rs @@ -50,7 +50,7 @@ fn makefile_task_condition_test(name: &str, expect_enabled: bool, linux_only: bo config: task, }; - let enabled = condition::validate_condition_for_step(&flow_info, &step); + let enabled = condition::validate_condition_for_step(&flow_info, &step).unwrap(); let should_be_enabled = if expect_enabled { if ci_only { @@ -98,7 +98,7 @@ fn makefile_coverage_test() { RunTaskInfo::Routing(ref routing_info) => { let flow_info = create_flow_info(&config); let (task_name, fork, parallel, cleanup_task) = - runner::get_sub_task_info_for_routing_info(&flow_info, routing_info); + runner::get_sub_task_info_for_routing_info(&flow_info, routing_info).unwrap(); let names = task_name.unwrap(); assert_eq!(names.len(), 1); assert_eq!(names[0], "coverage-kcov"); @@ -176,7 +176,7 @@ fn makefile_build_file_increment_no_file_test() { config: task, }; - runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); envmnt::remove("CARGO_MAKE_BUILD_NUMBER_FILE"); @@ -208,9 +208,9 @@ fn makefile_build_file_increment_file_exists_test() { config: task, }; - runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); - runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); - runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); + runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); + runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); envmnt::remove("CARGO_MAKE_BUILD_NUMBER_FILE"); @@ -245,5 +245,5 @@ fn makefile_build_file_increment_panic_invalid_data_test() { config: task, }; - runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + runner::run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } diff --git a/src/lib/descriptor/mod.rs b/src/lib/descriptor/mod.rs index 040ecaf1..d6ff1780 100755 --- a/src/lib/descriptor/mod.rs +++ b/src/lib/descriptor/mod.rs @@ -22,6 +22,7 @@ use fsio::path::from_path::FromPath; use indexmap::IndexMap; use crate::descriptor::env::{merge_env, merge_env_files, merge_env_scripts}; +use crate::error::CargoMakeError; use crate::plugin::descriptor::merge_plugins_config; use crate::types::{ Config, ConfigSection, EnvFile, EnvFileInfo, EnvValue, Extend, ExternalConfig, ModifyConfig, @@ -142,7 +143,7 @@ fn add_file_location_info( external_config } -fn run_load_script(external_config: &ExternalConfig) -> bool { +fn run_load_script(external_config: &ExternalConfig) -> Result { match external_config.config { Some(ref config) => { let load_script = config.get_load_script(); @@ -151,19 +152,19 @@ fn run_load_script(external_config: &ExternalConfig) -> bool { Some(ref script) => { debug!("Load script found."); - scriptengine::invoke_script_pre_flow(script, None, None, None, true, &vec![]); + scriptengine::invoke_script_pre_flow(script, None, None, None, true, &vec![])?; - true + Ok(true) } None => { debug!("No load script defined."); - false + Ok(false) } } } None => { debug!("No load script defined."); - false + Ok(false) } } } @@ -171,7 +172,7 @@ fn run_load_script(external_config: &ExternalConfig) -> bool { fn merge_external_configs( config: ExternalConfig, parent_config: ExternalConfig, -) -> Result { +) -> Result { // merge env files let mut parent_env_files = match parent_config.env_files { Some(env_files) => env_files, @@ -246,7 +247,7 @@ fn merge_external_configs( fn load_descriptor_extended_makefiles( parent_path: &str, extend_struct: &Extend, -) -> Result { +) -> Result { match extend_struct { Extend::Path(base_file) => load_external_descriptor(parent_path, &base_file, true, false), Extend::Options(extend_options) => { @@ -274,7 +275,7 @@ fn load_descriptor_extended_makefiles( /// Ensure the Makefile's min_version, if present, is older than cargo-make's /// currently running version. -fn check_makefile_min_version(external_descriptor: &str) -> Result<(), String> { +fn check_makefile_min_version(external_descriptor: &str) -> Result<(), CargoMakeError> { let value: toml::Value = match toml::from_str(&external_descriptor) { Ok(value) => value, // If there's an error parsing the file, let the caller function figure @@ -289,11 +290,7 @@ fn check_makefile_min_version(external_descriptor: &str) -> Result<(), String> { if let Some(ref min_version) = min_version { if version::is_newer_found(&min_version) { - return Err(format!( - "Unable to run, minimum required version is: {}", - &min_version - ) - .to_string()); + return Err(CargoMakeError::VersionTooOld(min_version.to_string())); } } @@ -305,7 +302,7 @@ fn load_external_descriptor( file_name: &str, force: bool, set_env: bool, -) -> Result { +) -> Result { debug!( "Loading tasks from file: {} base directory: {}", &file_name, &base_path @@ -331,7 +328,7 @@ fn load_external_descriptor( file_config = add_file_location_info(file_config, &absolute_file_path); - run_load_script(&file_config); + run_load_script(&file_config)?; match file_config.extend { Some(ref extend_struct) => { @@ -420,7 +417,7 @@ fn merge_base_config_and_external_config( external_config: ExternalConfig, env_map: Option>, late_merge: bool, -) -> Result { +) -> Result { let mut external_tasks = match external_config.tasks { Some(tasks) => tasks, None => IndexMap::new(), @@ -512,7 +509,7 @@ fn load_descriptors( stable: bool, experimental: bool, modify_core_tasks: Option, -) -> Result { +) -> Result { let default_config = load_internal_descriptors(stable, experimental, modify_core_tasks); let mut external_config = load_external_descriptor(".", file_name, force, true)?; @@ -583,7 +580,7 @@ pub fn load( force: bool, env_map: Option>, experimental: bool, -) -> Result { +) -> Result { // load extended descriptor only let mut config = load_descriptors(&file_name, force, env_map.clone(), false, false, None)?; diff --git a/src/lib/descriptor/mod_test.rs b/src/lib/descriptor/mod_test.rs index 1f29a9f2..dc556111 100755 --- a/src/lib/descriptor/mod_test.rs +++ b/src/lib/descriptor/mod_test.rs @@ -597,8 +597,10 @@ fn load_external_descriptor_min_version_broken_makefile_nopanic() { false, false ) - .err(), - Some("Unable to run, minimum required version is: 999.999.999".into()) + .err() + .unwrap() + .to_string(), + String::from("Unable to run, minimum required version is: 999.999.999") ); } @@ -621,7 +623,7 @@ fn load_external_descriptor_broken_makefile_panic() { fn run_load_script_no_config_section() { let external_config = ExternalConfig::new(); - let invoked = run_load_script(&external_config); + let invoked = run_load_script(&external_config).unwrap(); assert!(!invoked); } @@ -630,7 +632,7 @@ fn run_load_script_no_load_script() { let mut external_config = ExternalConfig::new(); external_config.config = Some(ConfigSection::new()); - let invoked = run_load_script(&external_config); + let invoked = run_load_script(&external_config).unwrap(); assert!(!invoked); } @@ -642,7 +644,7 @@ fn run_load_script_valid_load_script() { let mut external_config = ExternalConfig::new(); external_config.config = Some(config); - let invoked = run_load_script(&external_config); + let invoked = run_load_script(&external_config).unwrap(); assert!(invoked); } @@ -655,7 +657,7 @@ fn run_load_script_invalid_load_script() { let mut external_config = ExternalConfig::new(); external_config.config = Some(config); - run_load_script(&external_config); + run_load_script(&external_config).unwrap(); } #[test] @@ -674,7 +676,7 @@ fn run_load_script_valid_load_script_duckscript() { let mut external_config = ExternalConfig::new(); external_config.config = Some(config); - let invoked = run_load_script(&external_config); + let invoked = run_load_script(&external_config).unwrap(); assert!(invoked); assert!(envmnt::exists( @@ -927,8 +929,8 @@ fn check_makefile_min_version_bigger_min_version() { assert!(result.is_err()); assert_eq!( - result.err().unwrap(), - "Unable to run, minimum required version is: 999.999.999" + result.err().unwrap().to_string(), + String::from("Unable to run, minimum required version is: 999.999.999") ); } diff --git a/src/lib/environment/mod.rs b/src/lib/environment/mod.rs index c9f2295f..60d2e95b 100644 --- a/src/lib/environment/mod.rs +++ b/src/lib/environment/mod.rs @@ -11,6 +11,7 @@ mod mod_test; use crate::command; use crate::condition; +use crate::error::CargoMakeError; use crate::io; use crate::profile; use crate::scriptengine; @@ -293,7 +294,10 @@ fn set_env_files_for_config( all_loaded } -fn set_env_scripts(env_scripts: Vec, cli_arguments: &Vec) { +fn set_env_scripts( + env_scripts: Vec, + cli_arguments: &Vec, +) -> Result<(), CargoMakeError> { for env_script in env_scripts { if !env_script.is_empty() { scriptengine::invoke_script_pre_flow( @@ -303,9 +307,10 @@ fn set_env_scripts(env_scripts: Vec, cli_arguments: &Vec) { None, true, cli_arguments, - ); + )?; } } + Ok(()) } pub(crate) fn set_current_task_meta_info_env(env: IndexMap) { @@ -324,7 +329,7 @@ pub(crate) fn set_current_task_meta_info_env(env: IndexMap) { } /// Updates the env for the current execution based on the descriptor. -fn initialize_env(config: &Config, cli_args: &Vec) { +fn initialize_env(config: &Config, cli_args: &Vec) -> Result<(), CargoMakeError> { debug!("Initializing Env."); let additional_profiles = match config.config.additional_profiles { @@ -336,7 +341,7 @@ fn initialize_env(config: &Config, cli_args: &Vec) { set_env_for_config(config.env.clone(), additional_profiles, true); - set_env_scripts(config.env_scripts.clone(), cli_args); + set_env_scripts(config.env_scripts.clone(), cli_args) } fn setup_env_for_duckscript() { @@ -575,7 +580,7 @@ pub(crate) fn setup_env( task: &str, home: Option, time_summary_vec: &mut Vec<(String, u128)>, -) -> EnvInfo { +) -> Result { envmnt::set_bool("CARGO_MAKE", true); envmnt::set("CARGO_MAKE_TASK", &task); @@ -631,15 +636,15 @@ pub(crate) fn setup_env( // load env vars now = SystemTime::now(); - initialize_env(config, &cli_args.arguments.clone().unwrap_or(vec![])); + initialize_env(config, &cli_args.arguments.clone().unwrap_or(vec![]))?; time_summary::add(time_summary_vec, "[Setup Env - Vars]", now); - EnvInfo { + Ok(EnvInfo { rust_info: rustinfo, crate_info, git_info: gitinfo, ci_info: ci_info_struct, - } + }) } fn set_workspace_cwd(directory_path: &Path, force: bool) { diff --git a/src/lib/environment/mod_test.rs b/src/lib/environment/mod_test.rs index 2a78775f..89e791ad 100755 --- a/src/lib/environment/mod_test.rs +++ b/src/lib/environment/mod_test.rs @@ -1030,7 +1030,7 @@ fn initialize_env_all() { plugins: None, }; - initialize_env(&config, &vec![]); + initialize_env(&config, &vec![]).unwrap(); assert!(envmnt::exists("initialize_env_all_test")); assert!(envmnt::exists("CARGO_MAKE_ENV_FILE_TEST1")); @@ -1065,12 +1065,12 @@ fn setup_env_empty() { plugins: None, }; - setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]); + setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]).unwrap(); let mut value = envmnt::get_or_panic("CARGO_MAKE_TASK"); assert_eq!(value, "setup_env_empty1"); - setup_env(&cli_args, &config, "setup_env_empty2", None, &mut vec![]); + setup_env(&cli_args, &config, "setup_env_empty2", None, &mut vec![]).unwrap(); let delay = time::Duration::from_millis(10); thread::sleep(delay); @@ -1096,7 +1096,7 @@ fn setup_env_skip_git() { plugins: None, }; - let env_info = setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]); + let env_info = setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]).unwrap(); assert!(env_info.git_info.user_name.is_none()); } @@ -1117,7 +1117,7 @@ fn setup_env_skip_rust() { plugins: None, }; - let env_info = setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]); + let env_info = setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]).unwrap(); assert!(env_info.rust_info.channel.is_none()); } @@ -1138,7 +1138,7 @@ fn setup_env_skip_crate() { plugins: None, }; - let env_info = setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]); + let env_info = setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]).unwrap(); assert!(env_info.crate_info.dependencies.is_none()); } @@ -1188,7 +1188,7 @@ fn setup_env_cli_arguments() { envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]); + setup_env(&cli_args, &config, "setup_env_empty1", None, &mut vec![]).unwrap(); let value = envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"); assert_eq!(value, "arg1;arg2"); @@ -1219,7 +1219,7 @@ fn setup_env_values() { assert_eq!(envmnt::get_or("MY_ENV_KEY", "NONE"), "NONE".to_string()); assert_eq!(envmnt::get_or("MY_ENV_KEY2", "NONE"), "NONE".to_string()); - setup_env(&cli_args, &config, "set_env_values", None, &mut vec![]); + setup_env(&cli_args, &config, "set_env_values", None, &mut vec![]).unwrap(); assert_eq!(envmnt::get_or_panic("MY_ENV_KEY"), "MY_ENV_VALUE"); assert_eq!(envmnt::get_or_panic("MY_ENV_KEY2"), "MY_ENV_VALUE2"); @@ -1261,7 +1261,7 @@ fn setup_env_script() { "NONE".to_string() ); - setup_env(&cli_args, &config, "set_env_values", None, &mut vec![]); + setup_env(&cli_args, &config, "set_env_values", None, &mut vec![]).unwrap(); assert_eq!(envmnt::get_or_panic("MY_ENV_SCRIPT_KEY"), "MY_ENV_VALUE"); assert_eq!(envmnt::get_or_panic("MY_ENV_SCRIPT_KEY2"), "script1"); diff --git a/src/lib/error.rs b/src/lib/error.rs new file mode 100644 index 00000000..5d0ada29 --- /dev/null +++ b/src/lib/error.rs @@ -0,0 +1,170 @@ +use std::cmp::PartialEq; +use std::string::ToString; + +#[derive( + strum_macros::AsRefStr, + strum_macros::Display, + strum_macros::EnumDiscriminants, + strum_macros::IntoStaticStr, + Debug, +)] +#[repr(u16)] +pub enum CargoMakeError { + #[strum( + to_string = "A cycle between different env variables has been detected \ + (E001, see: https://github.com/sagiegurari/cargo-make#e001 for more information). {0}" + )] + EnvVarCycle(String) = 100, + + #[strum(to_string = "Detected cycle while resolving alias {0}: {1}")] + AliasCycle(String, String) = 101, + + #[strum(to_string = "Unable to run, minimum required version is: {0}")] + VersionTooOld(String) = 102, + + #[strum(to_string = "Error while executing command, unable to extract exit code.")] + ExitCodeValidation = 103, + + #[strum(to_string = "Error while executing command, exit code: {0}")] + ExitCodeError(i32) = 104, + + #[strum(to_string = "Unable to run, minimum required version is: {0}")] + NotFound(String) = 404, + + // ************************ + // * Library level errors * + // ************************ + #[strum(to_string = "`std::io::Error` error. {error:?}")] + StdIoError { error: std::io::Error } = 700, + + #[strum(to_string = "{0:?}")] + ExitCode(std::process::ExitCode) = 710, + + #[strum(to_string = "`toml::de::Error` error. {error:?}")] + TomlDeError { error: toml::de::Error } = 720, + + #[strum(to_string = "`fsio::error::FsIOError` error. {error:?}")] + FsIOError { error: fsio::error::FsIOError } = 730, + + #[strum(to_string = "`cliparser::types::ParserError` error. {error:?}")] + ParserError { + error: cliparser::types::ParserError, + } = 731, +} + +impl CargoMakeError { + fn discriminant(&self) -> u16 { + unsafe { *<*const _>::from(self).cast::() } + } +} + +impl From for CargoMakeError { + fn from(error: std::io::Error) -> Self { + Self::StdIoError { error } + } +} + +impl From for CargoMakeError { + fn from(error: toml::de::Error) -> Self { + Self::TomlDeError { error } + } +} + +impl From for CargoMakeError { + fn from(error: fsio::error::FsIOError) -> Self { + Self::FsIOError { error } + } +} // ::ParserError + +impl From for CargoMakeError { + fn from(error: cliparser::types::ParserError) -> Self { + Self::ParserError { error } + } +} + +impl From for CargoMakeError { + fn from(error: std::process::ExitCode) -> Self { + Self::ExitCode(error) + } +} + +impl std::process::Termination for CargoMakeError { + fn report(self) -> std::process::ExitCode { + if let CargoMakeError::ExitCode(exit_code) = self { + return exit_code; + } + let status_code = self.discriminant(); + if status_code > u8::MAX as u16 { + eprintln!("exit code {}", status_code); + std::process::ExitCode::FAILURE + } else { + std::process::ExitCode::from(status_code as u8) + } + } +} + +pub enum SuccessOrCargoMakeError { + Ok(T), + Err(CargoMakeError), +} + +impl From> for SuccessOrCargoMakeError { + fn from(value: Result) -> Self { + match value { + Ok(val) => SuccessOrCargoMakeError::Ok(val), + Err(error) => SuccessOrCargoMakeError::Err(error), + } + } +} + +// Can't use `Result` because +// [E0117] Only traits defined in the current crate can be implemented for arbitrary types +impl std::process::Termination for SuccessOrCargoMakeError { + fn report(self) -> std::process::ExitCode { + match self { + SuccessOrCargoMakeError::Ok(_) => std::process::ExitCode::SUCCESS, + SuccessOrCargoMakeError::Err(error) => { + if let CargoMakeError::StdIoError { ref error } = error { + if let Some(e) = error.raw_os_error() { + eprintln!("{}", e.to_string()); + return if e > u8::MAX as i32 { + eprintln!("exit code {}", e); + std::process::ExitCode::FAILURE + } else { + std::process::ExitCode::from(e as u8) + }; + } + } + eprintln!("{}", error.to_string()); + error.report() + } + } + } +} + +/* +// TODO: Get `Into` syntax working +impl std::ops::FromResidual> +for SuccessOrCargoMakeError +{ + fn from_residual(residual: Result) -> Self { + if let Err(e) = residual { + SuccessOrCargoMakeError::Err(e) + } else { + SuccessOrCargoMakeError::Ok(std::process::ExitCode::SUCCESS) + } + } +} + +impl std::ops::FromResidual> +for SuccessOrCargoMakeError +{ + fn from_residual(residual: Result) -> Self { + if let Err(e) = residual { + SuccessOrCargoMakeError::Err(e.into()) + } else { + SuccessOrCargoMakeError::Ok(std::process::ExitCode::SUCCESS) + } + } +} +*/ diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 6c8ba795..72a3bd97 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -8,6 +8,7 @@ mod execution_plan_test; use crate::environment; +use crate::error::CargoMakeError; use crate::logger; use crate::profile; use crate::proxy_task::create_proxy_task; @@ -26,7 +27,11 @@ use std::path::Path; /// /// # Panics /// if there is a cycle in the alias chain. -fn get_task_name_recursive(config: &Config, name: &str, seen: &mut Vec) -> Option { +fn get_task_name_recursive( + config: &Config, + name: &str, + seen: &mut Vec, +) -> Result { seen.push(name.to_string()); match config.tasks.get(name) { @@ -37,13 +42,16 @@ fn get_task_name_recursive(config: &Config, name: &str, seen: &mut Vec) Some(ref alias) if seen.contains(alias) => { let chain = seen.join(" -> "); error!("Detected cycle while resolving alias {}: {}", &name, chain); - panic!("Detected cycle while resolving alias {}: {}", &name, chain); + return Err(CargoMakeError::AliasCycle(String::from(name), chain)); } Some(ref alias) => get_task_name_recursive(config, alias, seen), - None => Some(name.to_string()), + None => Ok(name.to_string()), } } - None => None, + None => Err(CargoMakeError::NotFound(format!( + "Task \"{}\" not found", + name + ))), } } @@ -51,22 +59,26 @@ fn get_task_name_recursive(config: &Config, name: &str, seen: &mut Vec) /// /// # Panics /// if there is a cycle in the alias chain. -pub(crate) fn get_actual_task_name(config: &Config, name: &str) -> Option { +pub(crate) fn get_actual_task_name(config: &Config, name: &str) -> Result { let mut seen = Vec::new(); get_task_name_recursive(config, name, &mut seen) } /// Resolves alias and normalizes task. -/// -/// # Panics -/// if task is not found or there is a cycle in the alias chain. -pub(crate) fn get_normalized_task(config: &Config, name: &str, support_alias: bool) -> Task { - match get_optional_normalized_task(config, name, support_alias) { - Some(task) => task, +pub(crate) fn get_normalized_task( + config: &Config, + name: &str, + support_alias: bool, +) -> Result { + match get_optional_normalized_task(config, name, support_alias)? { + Some(task) => Ok(task), None => { error!("Task {} not found", &name); - panic!("Task {} not found", &name); + Err(CargoMakeError::NotFound(format!( + "Task \"{}\" not found", + &name + ))) } } } @@ -75,46 +87,46 @@ pub(crate) fn get_normalized_task(config: &Config, name: &str, support_alias: bo /// /// # Panics /// if there is a cycle in the alias chain. -fn get_optional_normalized_task(config: &Config, name: &str, support_alias: bool) -> Option { - let actual_task_name_option = if support_alias { +fn get_optional_normalized_task( + config: &Config, + name: &str, + support_alias: bool, +) -> Result, CargoMakeError> { + let actual_task_name = if support_alias { get_actual_task_name(config, name) } else { - Some(name.to_string()) - }; + Ok(name.to_string()) + }?; - match actual_task_name_option { - Some(actual_task_name) => match config.tasks.get(&actual_task_name) { - Some(task_config) => { - let mut clone_task = task_config.clone(); - let mut normalized_task = clone_task.get_normalized_task(); - - normalized_task = match normalized_task.extend { - Some(ref extended_task_name) => { - let mut extended_task = - get_normalized_task(config, extended_task_name, support_alias); - - if let Some(ref env) = normalized_task.env { - if env.len() == 2 - && env.contains_key("CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE") - && env.contains_key( - "CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY", - ) - { - normalized_task.env = None; - } + match config.tasks.get(&actual_task_name) { + Some(task_config) => { + let mut clone_task = task_config.clone(); + let mut normalized_task = clone_task.get_normalized_task(); + + normalized_task = match normalized_task.extend { + Some(ref extended_task_name) => { + let mut extended_task = + get_normalized_task(config, extended_task_name, support_alias)?; + + if let Some(ref env) = normalized_task.env { + if env.len() == 2 + && env.contains_key("CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE") + && env + .contains_key("CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY") + { + normalized_task.env = None; } - extended_task.extend(&normalized_task); - - extended_task } - None => normalized_task, - }; + extended_task.extend(&normalized_task); - Some(normalized_task) - } - None => None, - }, - None => None, + extended_task + } + None => normalized_task, + }; + + Ok(Some(normalized_task)) + } + None => Ok(None), } } @@ -297,10 +309,10 @@ fn is_workspace_flow( disable_workspace: bool, crate_info: &CrateInfo, sub_flow: bool, -) -> bool { +) -> Result { // determine if workspace flow is explicitly set and enabled in the requested task let (task_set_workspace, task_enable_workspace) = - match get_optional_normalized_task(config, task, true) { + match get_optional_normalized_task(config, task, true)? { Some(normalized_task) => match normalized_task.workspace { Some(enable_workspace) => (true, enable_workspace), None => (false, false), @@ -314,16 +326,16 @@ fn is_workspace_flow( || (crate_info.workspace.is_none() && !envmnt::is("CARGO_MAKE_WORKSPACE_EMULATION")) || envmnt::exists("CARGO_MAKE_CRATE_CURRENT_WORKSPACE_MEMBER") { - false + Ok(false) } else { // project is a workspace and wasn't disabled via cli, need to check requested task // use requested task's workspace flag if set if task_set_workspace { - task_enable_workspace + Ok(task_enable_workspace) } else { // use configured default workspace flag if set - config.config.default_to_workspace.unwrap_or(true) + Ok(config.config.default_to_workspace.unwrap_or(true)) } } } @@ -337,11 +349,11 @@ fn create_for_step( root: bool, allow_private: bool, skip_tasks_pattern: &Option, -) { +) -> Result<(), CargoMakeError> { if let Some(skip_tasks_pattern_regex) = skip_tasks_pattern { if skip_tasks_pattern_regex.is_match(&task.name) { debug!("Skipping task: {} due to skip pattern.", &task.name); - return; + return Ok(()); } } @@ -371,10 +383,10 @@ fn create_for_step( steps.push(step); task_names.insert(task.to_string()); - return; + return Ok(()); } - let task_config = get_normalized_task(config, &task.name, true); + let task_config = get_normalized_task(config, &task.name, true)?; debug!("Normalized Task: {} config: {:#?}", &task, &task_config); @@ -398,7 +410,7 @@ fn create_for_step( false, true, skip_tasks_pattern, - ); + )?; } } _ => debug!("No dependencies found for task: {}", &task), @@ -418,10 +430,15 @@ fn create_for_step( error!("Task {} is private", &task); panic!("Task {} is private", &task); } + Ok(()) } -fn add_predefined_step(config: &Config, task: &str, steps: &mut Vec) { - let task_config = get_normalized_task(config, task, false); +fn add_predefined_step( + config: &Config, + task: &str, + steps: &mut Vec, +) -> Result<(), CargoMakeError> { + let task_config = get_normalized_task(config, task, false)?; let add = !task_config.disabled.unwrap_or(false); if add { @@ -430,6 +447,7 @@ fn add_predefined_step(config: &Config, task: &str, steps: &mut Vec) { config: task_config, }); } + Ok(()) } /// Creates the full execution plan @@ -441,17 +459,17 @@ pub(crate) fn create( allow_private: bool, sub_flow: bool, skip_tasks_pattern: &Option, -) -> ExecutionPlan { +) -> Result { let mut task_names = HashSet::new(); let mut steps = Vec::new(); if !sub_flow { match config.config.legacy_migration_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), + Some(ref task) => add_predefined_step(config, task, &mut steps)?, None => debug!("Legacy migration task not defined."), }; match config.config.init_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), + Some(ref task) => add_predefined_step(config, task, &mut steps)?, None => debug!("Init task not defined."), }; } @@ -463,7 +481,7 @@ pub(crate) fn create( if !skip { let workspace_flow = - is_workspace_flow(&config, &task, disable_workspace, &crate_info, sub_flow); + is_workspace_flow(&config, &task, disable_workspace, &crate_info, sub_flow)?; if workspace_flow { let workspace_task = create_workspace_task(crate_info, task); @@ -481,7 +499,7 @@ pub(crate) fn create( true, allow_private, &skip_tasks_pattern, - ); + )?; } } else { debug!("Skipping task: {} due to skip pattern.", &task); @@ -490,10 +508,10 @@ pub(crate) fn create( if !sub_flow { // always add end task even if already executed due to some dependency match config.config.end_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), + Some(ref task) => add_predefined_step(config, task, &mut steps)?, None => debug!("Ent task not defined."), }; } - ExecutionPlan { steps } + Ok(ExecutionPlan { steps }) } diff --git a/src/lib/execution_plan_test.rs b/src/lib/execution_plan_test.rs index 4778fb99..f1a2267f 100644 --- a/src/lib/execution_plan_test.rs +++ b/src/lib/execution_plan_test.rs @@ -15,7 +15,13 @@ fn get_actual_task_name_not_found() { let name = get_actual_task_name(&config, "test"); - assert!(name.is_none()); + assert_eq!( + format!("{:?}", name.err().unwrap()), + format!( + "{:?}", + CargoMakeError::NotFound(String::from("Task \"test\" not found")) + ) + ); } #[test] @@ -74,7 +80,7 @@ fn get_actual_task_name_alias_self_referential() { task.alias = Some("rec".to_string()); config.tasks.insert("rec".to_string(), task); - get_actual_task_name(&config, "rec"); + get_actual_task_name(&config, "rec").unwrap(); } #[test] @@ -98,7 +104,7 @@ fn get_actual_task_name_alias_circular() { config.tasks.insert("rec-mut-a".to_string(), task_a); config.tasks.insert("rec-mut-b".to_string(), task_b); - get_actual_task_name(&config, "rec-mut-a"); + get_actual_task_name(&config, "rec-mut-a").unwrap(); } #[test] @@ -481,7 +487,7 @@ fn is_workspace_flow_true_default() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); assert!(workspace_flow); } @@ -512,7 +518,7 @@ fn is_workspace_flow_false_in_config() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); assert!(!workspace_flow); } @@ -543,7 +549,7 @@ fn is_workspace_flow_true_in_config() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); assert!(workspace_flow); } @@ -572,7 +578,7 @@ fn is_workspace_flow_true_in_task() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); assert!(workspace_flow); } @@ -600,7 +606,7 @@ fn is_workspace_flow_default_false_in_task_and_sub_flow() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true).unwrap(); assert!(!workspace_flow); } @@ -629,7 +635,7 @@ fn is_workspace_flow_true_in_task_and_sub_flow() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true).unwrap(); assert!(workspace_flow); } @@ -658,7 +664,7 @@ fn is_workspace_flow_false_in_task_and_sub_flow() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true).unwrap(); assert!(!workspace_flow); } @@ -683,7 +689,7 @@ fn is_workspace_flow_task_not_defined() { plugins: None, }; - let workspace_flow = is_workspace_flow(&config, "notfound", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "notfound", false, &crate_info, false).unwrap(); assert!(workspace_flow); } @@ -705,7 +711,7 @@ fn is_workspace_flow_no_workspace() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); assert!(!workspace_flow); } @@ -734,7 +740,7 @@ fn is_workspace_flow_disabled_via_cli() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", true, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", true, &crate_info, false).unwrap(); assert!(!workspace_flow); } @@ -763,7 +769,7 @@ fn is_workspace_flow_disabled_via_task() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); assert!(!workspace_flow); } @@ -797,7 +803,8 @@ fn create_single() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -834,7 +841,8 @@ fn create_single_disabled() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "end"); @@ -871,7 +879,8 @@ fn create_single_private() { false, false, &None, - ); + ) + .unwrap(); } #[test] @@ -904,7 +913,8 @@ fn create_single_allow_private() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test-private"); @@ -946,7 +956,8 @@ fn create_with_dependencies() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "task_dependency"); @@ -992,7 +1003,8 @@ fn create_with_foreign_dependencies_directory() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1043,7 +1055,8 @@ fn create_with_foreign_dependencies_filename() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1094,7 +1107,8 @@ fn create_with_foreign_dependencies_file_and_directory() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1134,7 +1148,8 @@ fn create_with_dependencies_sub_flow() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create(&config, "test", &CrateInfo::new(), false, true, true, &None); + let execution_plan = + create(&config, "test", &CrateInfo::new(), false, true, true, &None).unwrap(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "task_dependency"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -1176,7 +1191,8 @@ fn create_disabled_task_with_dependencies() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "end"); @@ -1218,7 +1234,8 @@ fn create_with_dependencies_disabled() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -1335,7 +1352,8 @@ fn create_platform_disabled() { true, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 0); } @@ -1377,7 +1395,8 @@ fn create_with_dependencies_and_skip_filter() { true, false, &Some(skip_filter), - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "task_dependency"); @@ -1403,7 +1422,7 @@ fn create_workspace() { env::set_current_dir("./examples/workspace").unwrap(); let crateinfo = environment::crateinfo::load(); - let execution_plan = create(&config, "test", &crateinfo, false, true, false, &None); + let execution_plan = create(&config, "test", &crateinfo, false, true, false, &None).unwrap(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "workspace"); @@ -1427,7 +1446,7 @@ fn create_noworkspace() { env::set_current_dir("./examples/workspace").unwrap(); let crateinfo = environment::crateinfo::load(); - let execution_plan = create(&config, "test", &crateinfo, true, true, false, &None); + let execution_plan = create(&config, "test", &crateinfo, true, true, false, &None).unwrap(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "test"); @@ -1452,7 +1471,8 @@ fn create_task_extends_empty_env_bug_verification() { false, false, &None, - ); + ) + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); @@ -1588,7 +1608,7 @@ fn get_normalized_task_multi_extend() { config.tasks.insert("2".to_string(), task2); config.tasks.insert("3".to_string(), task3); - let task = get_normalized_task(&config, "3", true); + let task = get_normalized_task(&config, "3", true).unwrap(); assert_eq!(task.category.unwrap(), "2"); assert_eq!(task.description.unwrap(), "1"); @@ -1616,7 +1636,7 @@ fn get_normalized_task_simple() { }; config.tasks.insert("1".to_string(), task1); - let task = get_normalized_task(&config, "1", true); + let task = get_normalized_task(&config, "1", true).unwrap(); assert_eq!(task.category.unwrap(), "1"); assert_eq!(task.description.unwrap(), "1"); diff --git a/src/lib/installer/cargo_plugin_installer.rs b/src/lib/installer/cargo_plugin_installer.rs index 4d1cd129..44db7df8 100644 --- a/src/lib/installer/cargo_plugin_installer.rs +++ b/src/lib/installer/cargo_plugin_installer.rs @@ -8,6 +8,7 @@ mod cargo_plugin_installer_test; use crate::command; +use crate::error::CargoMakeError; use crate::installer::crate_version_check; use crate::toolchain::wrap_command; use crate::types::ToolchainSpecifier; @@ -59,7 +60,10 @@ fn is_crate_in_list_output(crate_name: &str, output: &str) -> bool { false } -fn is_crate_installed(toolchain: &Option, crate_name: &str) -> bool { +fn is_crate_installed( + toolchain: &Option, + crate_name: &str, +) -> Result { debug!("Getting list of installed cargo commands."); let mut command_struct = match toolchain { @@ -78,19 +82,19 @@ fn is_crate_installed(toolchain: &Option, crate_name: &str) match result { Ok(output) => { let exit_code = command::get_exit_code(Ok(output.status), false); - command::validate_exit_code(exit_code); + command::validate_exit_code(exit_code)?; let stdout = strip_str(String::from_utf8_lossy(&output.stdout)); let crate_name_trimmed = crate_name.trim(); - is_crate_in_list_output(&crate_name_trimmed, &stdout) - || is_crate_in_list_output_legacy(&crate_name_trimmed, &stdout) + Ok(is_crate_in_list_output(&crate_name_trimmed, &stdout) + || is_crate_in_list_output_legacy(&crate_name_trimmed, &stdout)) } Err(error) => { error!( "Unable to check if crate is installed: {} {:#?}", crate_name, &error ); - false + Ok(false) } } } @@ -154,11 +158,11 @@ pub(crate) fn install_crate( min_version: &Option, install_command: &Option, allow_force: &Option, -) { +) -> Result<(), CargoMakeError> { let installed = match cargo_command { Some(cargo_command) => is_crate_installed(&toolchain, cargo_command), - None => false, - }; + None => Ok(false), + }?; let mut force = false; let allow_force_value = allow_force.unwrap_or(true); let run_installation = if !installed { @@ -186,9 +190,10 @@ pub(crate) fn install_crate( match toolchain { Some(ref toolchain_string) => { let command_spec = wrap_command(&toolchain_string, "cargo", &Some(install_args)); - command::run_command(&command_spec.command, &command_spec.args, validate) + command::run_command(&command_spec.command, &command_spec.args, validate)? } - None => command::run_command("cargo", &Some(install_args), validate), + None => command::run_command("cargo", &Some(install_args), validate)?, }; } + Ok(()) } diff --git a/src/lib/installer/cargo_plugin_installer_test.rs b/src/lib/installer/cargo_plugin_installer_test.rs index c62f29c0..37910b16 100644 --- a/src/lib/installer/cargo_plugin_installer_test.rs +++ b/src/lib/installer/cargo_plugin_installer_test.rs @@ -3,19 +3,19 @@ use crate::test; #[test] fn is_crate_installed_true_core() { - let output = is_crate_installed(&None, "test"); + let output = is_crate_installed(&None, "test").unwrap(); assert!(output); } #[test] fn is_crate_installed_true_plugin() { - let output = is_crate_installed(&None, "make"); + let output = is_crate_installed(&None, "make").unwrap(); assert!(output); } #[test] fn is_crate_installed_false() { - let output = is_crate_installed(&None, "badbadbad"); + let output = is_crate_installed(&None, "badbadbad").unwrap(); assert!(!output); } @@ -24,7 +24,7 @@ fn is_crate_installed_with_toolchain_true() { if test::is_not_rust_stable() { let toolchain = test::get_toolchain(); - let output = is_crate_installed(&Some(toolchain), "test"); + let output = is_crate_installed(&Some(toolchain), "test").unwrap(); assert!(output); } } @@ -34,7 +34,7 @@ fn is_crate_installed_with_toolchain_false() { if test::is_not_rust_stable() { let toolchain = test::get_toolchain(); - let output = is_crate_installed(&Some(toolchain), "badbadbad"); + let output = is_crate_installed(&Some(toolchain), "badbadbad").unwrap(); assert!(!output); } } @@ -235,7 +235,7 @@ fn should_skip_crate_name_git() { #[test] fn install_crate_already_installed_test() { - install_crate(&None, Some("test"), "bad", &None, true, &None, &None, &None); + install_crate(&None, Some("test"), "bad", &None, true, &None, &None, &None).unwrap(); } #[test] @@ -249,12 +249,13 @@ fn install_crate_already_installed_cargo_make() { &None, &None, &None, - ); + ) + .unwrap(); } #[test] fn install_crate_already_installed_cargo_make_without_check() { - install_crate(&None, None, "cargo-make", &None, true, &None, &None, &None); + install_crate(&None, None, "cargo-make", &None, true, &None, &None, &None).unwrap(); } #[test] @@ -277,7 +278,8 @@ fn install_crate_already_installed_min_version_equal() { &Some(version_string), &None, &None, - ); + ) + .unwrap(); } #[test] @@ -308,5 +310,6 @@ fn install_crate_already_installed_min_version_smaller() { &Some(version_string), &None, &None, - ); + ) + .unwrap(); } diff --git a/src/lib/installer/crate_installer.rs b/src/lib/installer/crate_installer.rs index 485573b8..7e98be0b 100644 --- a/src/lib/installer/crate_installer.rs +++ b/src/lib/installer/crate_installer.rs @@ -8,6 +8,7 @@ mod crate_installer_test; use crate::command; +use crate::error::CargoMakeError; use crate::installer::crate_version_check; use crate::installer::{cargo_plugin_installer, rustup_component_installer}; use crate::toolchain::wrap_command; @@ -32,7 +33,7 @@ fn invoke_cargo_install( info: &InstallCrateInfo, args: &Option>, validate: bool, -) { +) -> Result<(), CargoMakeError> { let (automatic_lock_version, version_option) = if info.min_version.is_some() { (false, &info.min_version) } else { @@ -63,11 +64,13 @@ fn invoke_cargo_install( }, }; - command::run_command(&command_spec.command, &command_spec.args, validate); + command::run_command(&command_spec.command, &command_spec.args, validate)?; if remove_lock { envmnt::remove("CARGO_MAKE_CRATE_INSTALLATION_LOCKED"); } + + Ok(()) } fn is_crate_only_info(info: &InstallCrateInfo) -> bool { @@ -82,7 +85,7 @@ pub(crate) fn install( info: &InstallCrateInfo, args: &Option>, validate: bool, -) { +) -> Result<(), CargoMakeError> { let installed = rustup_component_installer::is_installed(&toolchain, &info.binary, &info.test_arg); let crate_only_info = is_crate_only_info(&info); @@ -112,7 +115,8 @@ pub(crate) fn install( debug!("Crate: {} not installed.", &info.crate_name); if !invoke_rustup_install(&toolchain, &info) { - invoke_cargo_install(&toolchain, &info, &args, validate); + invoke_cargo_install(&toolchain, &info, &args, validate)?; } } + Ok(()) } diff --git a/src/lib/installer/crate_installer_test.rs b/src/lib/installer/crate_installer_test.rs index bec28bee..68983401 100644 --- a/src/lib/installer/crate_installer_test.rs +++ b/src/lib/installer/crate_installer_test.rs @@ -97,7 +97,7 @@ fn invoke_cargo_install_test() { force: None, }; - invoke_cargo_install(&None, &info, &None, false); + invoke_cargo_install(&None, &info, &None, false).unwrap(); } #[test] @@ -117,7 +117,7 @@ fn invoke_cargo_install_with_toolchain_test() { force: None, }; - invoke_cargo_install(&Some(toolchain), &info, &None, false); + invoke_cargo_install(&Some(toolchain), &info, &None, false).unwrap(); } #[test] @@ -135,7 +135,7 @@ fn install_test_test() { force: None, }; - install(&None, &info, &None, false); + install(&None, &info, &None, false).unwrap(); } #[test] @@ -155,7 +155,7 @@ fn install_test_with_toolchain_test() { force: None, }; - install(&Some(toolchain), &info, &None, false); + install(&Some(toolchain), &info, &None, false).unwrap(); } #[test] @@ -173,7 +173,7 @@ fn install_already_installed_crate_only() { force: None, }; - install(&None, &info, &None, false); + install(&None, &info, &None, false).unwrap(); } #[test] @@ -199,7 +199,7 @@ fn install_already_installed_crate_only_min_version_equal() { force: None, }; - install(&None, &info, &None, false); + install(&None, &info, &None, false).unwrap(); } #[test] @@ -233,7 +233,7 @@ fn install_already_installed_crate_only_min_version_smaller() { force: None, }; - install(&None, &info, &None, false); + install(&None, &info, &None, false).unwrap(); } #[test] @@ -259,7 +259,7 @@ fn install_already_installed_crate_only_version_equal() { force: None, }; - install(&None, &info, &None, false); + install(&None, &info, &None, false).unwrap(); } #[test] diff --git a/src/lib/installer/mod.rs b/src/lib/installer/mod.rs index 28d01ec5..19368cec 100644 --- a/src/lib/installer/mod.rs +++ b/src/lib/installer/mod.rs @@ -15,6 +15,7 @@ pub(crate) mod rustup_component_installer; #[path = "mod_test.rs"] mod mod_test; +use crate::error::CargoMakeError; use crate::scriptengine; use crate::types::{FlowInfo, FlowState, InstallCrate, Task}; use std::cell::RefCell; @@ -63,7 +64,7 @@ pub(crate) fn install( task_config: &Task, flow_info: &FlowInfo, flow_state: Rc>, -) { +) -> Result<(), CargoMakeError> { let validate = !task_config.should_ignore_errors(); let toolchain = task_config.toolchain.clone(); @@ -104,7 +105,7 @@ pub(crate) fn install( &None, &Some(false), // we can't validate, so we do not allow force ), - }; + }?; } InstallCrate::CargoPluginInfo(ref install_info) => { let (cargo_command, crate_name) = @@ -139,14 +140,14 @@ pub(crate) fn install( &install_info.min_version, &install_info.install_command, &install_info.force, - ); + )?; } InstallCrate::CrateInfo(ref install_info) => crate_installer::install( &toolchain, install_info, &task_config.install_crate_args, validate, - ), + )?, InstallCrate::RustupComponentInfo(ref install_info) => { rustup_component_installer::install(&toolchain, install_info, validate); } @@ -161,7 +162,7 @@ pub(crate) fn install( validate, Some(flow_info), Some(flow_state), - ); + )?; () } None => match get_cargo_plugin_info_from_command(&task_config) { @@ -175,10 +176,11 @@ pub(crate) fn install( &None, &None, &None, - ); + )?; } None => debug!("No installation script defined."), }, }, - } + }; + Ok(()) } diff --git a/src/lib/installer/mod_test.rs b/src/lib/installer/mod_test.rs index 339c586b..1155619f 100644 --- a/src/lib/installer/mod_test.rs +++ b/src/lib/installer/mod_test.rs @@ -66,7 +66,8 @@ fn install_empty() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -80,7 +81,8 @@ fn install_disabled_bad_crate() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -95,7 +97,8 @@ fn install_empty_args() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -109,7 +112,8 @@ fn install_enabled_crate_already_installed() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -123,7 +127,8 @@ fn install_crate_already_installed() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -137,7 +142,8 @@ fn install_crate_missing_cargo_command() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -150,7 +156,8 @@ fn install_crate_auto_detect_already_installed() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -164,7 +171,8 @@ fn install_crate_auto_detect_unable_to_install() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -190,7 +198,8 @@ fn install_rustup_via_crate_info() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -211,7 +220,8 @@ fn install_rustup_via_rustup_info() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -223,7 +233,8 @@ fn install_script_ok() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -236,7 +247,8 @@ fn install_script_error() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } #[test] @@ -256,7 +268,8 @@ fn install_script_duckscript() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(envmnt::exists("install_script_duckscript")); assert!(envmnt::is_or("install_script_duckscript", false)); @@ -272,5 +285,6 @@ fn install_script_error_ignore_errors() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); } diff --git a/src/lib/mod.rs b/src/lib/mod.rs index e12397ed..49763cd1 100755 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -34,8 +34,8 @@ //! [Apache 2](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) open source license. //! -use either::Either; // Dependencies used in the binary `makers`: +use crate::error::CargoMakeError; use crate::types::CliArgs; #[cfg(windows)] use nu_ansi_term as _; @@ -60,6 +60,7 @@ mod condition; pub mod config; mod descriptor; mod environment; +pub mod error; mod execution_plan; mod functions; mod installer; @@ -78,6 +79,6 @@ mod toolchain; mod version; /// Handles the command line arguments and executes the runner. -pub fn run_cli(command_name: String, sub_command: bool) -> Either { +pub fn run_cli(command_name: String, sub_command: bool) -> Result { cli::run_cli(command_name, sub_command) } diff --git a/src/lib/plugin/sdk/cm_plugin_check_task_condition.rs b/src/lib/plugin/sdk/cm_plugin_check_task_condition.rs index 4acdfa40..1be2a605 100644 --- a/src/lib/plugin/sdk/cm_plugin_check_task_condition.rs +++ b/src/lib/plugin/sdk/cm_plugin_check_task_condition.rs @@ -29,7 +29,10 @@ impl Command for CommandImpl { fn run(&self, _arguments: Vec) -> CommandResult { let passed = runner::validate_condition(&self.flow_info, &self.step); - CommandResult::Continue(Some(passed.to_string())) + match passed { + Ok(r) => CommandResult::Continue(Some(r.to_string())), + Err(e) => CommandResult::Error(e.to_string()), + } } } diff --git a/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs b/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs index bedb6ced..d75bc405 100644 --- a/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs +++ b/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs @@ -85,7 +85,7 @@ set_env FORCE_PLUGIN_SET_AND_CLEAR_FLOW_TEST_SET_4 1 "FORCE_PLUGIN_SET_AND_CLEAR_FLOW_TEST_SET_4" )); - runner::run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + runner::run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false).unwrap(); assert!(envmnt::is_equal( "FORCE_PLUGIN_SET_AND_CLEAR_FLOW_TEST_SET", diff --git a/src/lib/plugin/sdk/cm_plugin_run_custom_task.rs b/src/lib/plugin/sdk/cm_plugin_run_custom_task.rs index d02ab751..e4fd2f2b 100644 --- a/src/lib/plugin/sdk/cm_plugin_run_custom_task.rs +++ b/src/lib/plugin/sdk/cm_plugin_run_custom_task.rs @@ -47,12 +47,14 @@ impl Command for CommandImpl { plugins_enabled: false, }; - runner::run_task_with_options( + if let Err(e) = runner::run_task_with_options( &self.flow_info, self.flow_state.clone(), &custom_step, &options, - ); + ) { + return CommandResult::Error(e.to_string()); + } CommandResult::Continue(Some("true".to_string())) } diff --git a/src/lib/plugin/sdk/cm_plugin_run_task.rs b/src/lib/plugin/sdk/cm_plugin_run_task.rs index 2b5d9da7..ddcbf082 100644 --- a/src/lib/plugin/sdk/cm_plugin_run_task.rs +++ b/src/lib/plugin/sdk/cm_plugin_run_task.rs @@ -34,12 +34,14 @@ impl Command for CommandImpl { plugins_enabled: false, }; - runner::run_task_with_options( + if let Err(e) = runner::run_task_with_options( &self.flow_info, self.flow_state.clone(), &self.step, &options, - ); + ) { + return CommandResult::Error(e.to_string()); + } CommandResult::Continue(Some("true".to_string())) } diff --git a/src/lib/runner.rs b/src/lib/runner.rs index 0ba358b3..807bc429 100755 --- a/src/lib/runner.rs +++ b/src/lib/runner.rs @@ -15,6 +15,7 @@ mod runner_test; use crate::command; use crate::condition; use crate::environment; +use crate::error::CargoMakeError; use crate::execution_plan::create as create_execution_plan; use crate::functions; use crate::installer; @@ -36,9 +37,10 @@ use std::rc::Rc; use std::thread; use std::time::SystemTime; -fn do_in_task_working_directory(step: &Step, mut action: F) +fn do_in_task_working_directory(step: &Step, mut action: F) -> Result<(), CargoMakeError> where - F: FnMut(), + // fn() -> Result<(), CargoMakeError> + F: FnMut() -> Result, { let revert_directory = match step.config.cwd { Some(ref cwd) => { @@ -57,7 +59,7 @@ where None => "".to_string(), }; - action(); + action()?; // revert to original cwd match step.config.cwd { @@ -66,24 +68,29 @@ where } _ => (), }; + Ok(()) } -pub(crate) fn validate_condition(flow_info: &FlowInfo, step: &Step) -> bool { +pub(crate) fn validate_condition( + flow_info: &FlowInfo, + step: &Step, +) -> Result { let mut valid = true; - let do_validate = || { - valid = condition::validate_condition_for_step(&flow_info, &step); + let do_validate = || -> Result { + valid = condition::validate_condition_for_step(&flow_info, &step)?; + Ok(valid) }; - do_in_task_working_directory(&step, do_validate); + do_in_task_working_directory(&step, do_validate)?; - valid + Ok(valid) } pub(crate) fn get_sub_task_info_for_routing_info( flow_info: &FlowInfo, routing_info: &Vec, -) -> (Option>, bool, bool, Option) { +) -> Result<(Option>, bool, bool, Option), CargoMakeError> { let mut task_name = None; let mut fork = false; @@ -96,7 +103,7 @@ pub(crate) fn get_sub_task_info_for_routing_info( &routing_step.condition_script, None, routing_step.condition_script_runner_args.clone(), - ); + )?; if invoke { let task_name_values = match routing_step.name.clone() { @@ -111,7 +118,7 @@ pub(crate) fn get_sub_task_info_for_routing_info( } } - (task_name, fork, parallel, cleanup_task) + Ok((task_name, fork, parallel, cleanup_task)) } fn create_fork_step(flow_info: &FlowInfo) -> Step { @@ -129,7 +136,11 @@ fn create_fork_step(flow_info: &FlowInfo) -> Step { } } -fn run_cleanup_task(flow_info: &FlowInfo, flow_state: Rc>, task: &str) { +fn run_cleanup_task( + flow_info: &FlowInfo, + flow_state: Rc>, + task: &str, +) -> Result<(), CargoMakeError> { match flow_info.config.tasks.get(task) { Some(cleanup_task_info) => run_task( &flow_info, @@ -139,7 +150,10 @@ fn run_cleanup_task(flow_info: &FlowInfo, flow_state: Rc>, ta config: cleanup_task_info.clone(), }, ), - None => error!("Cleanup task: {} not found.", &task), + None => Err(CargoMakeError::NotFound(format!( + "Cleanup task: {} not found.", + &task + ))), } } @@ -147,7 +161,7 @@ fn run_forked_task( flow_info: &FlowInfo, flow_state: Rc>, cleanup_task: &Option, -) { +) -> Result<(), CargoMakeError> { // run task as a sub process let step = create_fork_step(&flow_info); @@ -155,11 +169,13 @@ fn run_forked_task( Some(cleanup_task_name) => { // run the forked task (forked tasks only run a command + args) let exit_code = - command::run_command(&step.config.command.unwrap(), &step.config.args, false); + command::run_command(&step.config.command.unwrap(), &step.config.args, false)?; if exit_code != 0 { - run_cleanup_task(&flow_info, flow_state, &cleanup_task_name); - command::validate_exit_code(exit_code); + run_cleanup_task(&flow_info, flow_state, &cleanup_task_name)?; + command::validate_exit_code(exit_code) + } else { + Ok(()) } } None => run_task(&flow_info, flow_state, &step), @@ -171,7 +187,7 @@ fn run_sub_task_and_report( flow_info: &FlowInfo, flow_state: Rc>, sub_task: &RunTaskInfo, -) -> bool { +) -> Result { let (task_names, fork, parallel, cleanup_task) = match sub_task { RunTaskInfo::Name(ref name) => (Some(vec![name.to_string()]), false, false, None), RunTaskInfo::Details(ref details) => { @@ -187,7 +203,7 @@ fn run_sub_task_and_report( ) } RunTaskInfo::Routing(ref routing_info) => { - get_sub_task_info_for_routing_info(&flow_info, routing_info) + get_sub_task_info_for_routing_info(&flow_info, routing_info)? } }; @@ -204,14 +220,15 @@ fn run_sub_task_and_report( let task_run_fn = move |flow_info: &FlowInfo, flow_state: Rc>, fork: bool, - cleanup_task: &Option| { + cleanup_task: &Option| + -> Result<(), CargoMakeError> { let mut sub_flow_info = flow_info.clone(); sub_flow_info.task = name; if fork { - run_forked_task(&sub_flow_info, flow_state, cleanup_task); + run_forked_task(&sub_flow_info, flow_state, cleanup_task) } else { - run_flow(&sub_flow_info, flow_state, true); + run_flow(&sub_flow_info, flow_state, true) } }; @@ -220,37 +237,41 @@ fn run_sub_task_and_report( // we do not support merging changes back to parent let cloned_flow_state = flow_state.borrow().clone(); let cloned_cleanup_task = cleanup_task.clone(); - threads.push(thread::spawn(move || { + threads.push(thread::spawn(move || -> Result<(), CargoMakeError> { task_run_fn( &run_flow_info, Rc::new(RefCell::new(cloned_flow_state)), fork, &cloned_cleanup_task, - ); + ) })); } else { - task_run_fn(&flow_info, flow_state.clone(), fork, &cleanup_task); + task_run_fn(&flow_info, flow_state.clone(), fork, &cleanup_task)?; } } if threads.len() > 0 { for task_thread in threads { - task_thread.join().unwrap(); + task_thread.join().unwrap()?; } } if let Some(cleanup_task_name) = cleanup_task { - run_cleanup_task(&flow_info, flow_state, &cleanup_task_name); + run_cleanup_task(&flow_info, flow_state, &cleanup_task_name)?; } - true + Ok(true) } else { - false + Ok(false) } } -fn run_sub_task(flow_info: &FlowInfo, flow_state: Rc>, sub_task: &RunTaskInfo) { - run_sub_task_and_report(&flow_info, flow_state, &sub_task); +fn run_sub_task( + flow_info: &FlowInfo, + flow_state: Rc>, + sub_task: &RunTaskInfo, +) -> Result { + run_sub_task_and_report(&flow_info, flow_state, &sub_task) } fn create_watch_task_name(task: &str) -> String { @@ -277,10 +298,10 @@ fn watch_task( flow_state: Rc>, task: &str, options: Option, -) { +) -> Result<(), CargoMakeError> { let step = create_watch_step(&task, options, flow_info); - run_task(&flow_info, flow_state, &step); + run_task(&flow_info, flow_state, &step) } fn is_watch_enabled() -> bool { @@ -303,12 +324,16 @@ fn should_watch(task: &Task) -> bool { } } -pub(crate) fn run_task(flow_info: &FlowInfo, flow_state: Rc>, step: &Step) { +pub(crate) fn run_task( + flow_info: &FlowInfo, + flow_state: Rc>, + step: &Step, +) -> Result<(), CargoMakeError> { let options = RunTaskOptions { plugins_enabled: true, }; - run_task_with_options(flow_info, flow_state, step, &options); + run_task_with_options(flow_info, flow_state, step, &options) } pub(crate) fn run_task_with_options( @@ -316,7 +341,7 @@ pub(crate) fn run_task_with_options( flow_state: Rc>, step: &Step, options: &RunTaskOptions, -) { +) -> Result<(), CargoMakeError> { let start_time = SystemTime::now(); // if a plugin is handling the task execution flow @@ -326,7 +351,7 @@ pub(crate) fn run_task_with_options( &step.name, start_time, ); - return; + return Ok(()); } if step.config.is_actionable() { @@ -335,7 +360,7 @@ pub(crate) fn run_task_with_options( None => (), }; - if validate_condition(&flow_info, &step) { + if validate_condition(&flow_info, &step)? { if logger::should_reduce_output(&flow_info) && step.config.script.is_none() { debug!("Running Task: {}", &step.name); } else { @@ -397,11 +422,12 @@ pub(crate) fn run_task_with_options( flow_state, &step.name, step.config.watch.clone(), - ); + )?; } else { - do_in_task_working_directory(&step, || { - installer::install(&updated_step.config, flow_info, flow_state.clone()); - }); + do_in_task_working_directory(&step, || -> Result { + installer::install(&updated_step.config, flow_info, flow_state.clone())?; + Ok(true) + })?; match step.config.run_task { Some(ref sub_task) => { @@ -411,22 +437,23 @@ pub(crate) fn run_task_with_options( start_time, ); - run_sub_task(&flow_info, flow_state, sub_task); + run_sub_task(&flow_info, flow_state, sub_task)?; } None => { - do_in_task_working_directory(&step, || { + do_in_task_working_directory(&step, || -> Result { // run script let script_runner_done = scriptengine::invoke( &updated_step.config, flow_info, flow_state.clone(), - ); + )?; // run command if !script_runner_done { - command::run(&updated_step); + command::run(&updated_step)?; }; - }); + Ok(true) + })?; time_summary::add( &mut flow_state.borrow_mut().time_summary, @@ -454,16 +481,19 @@ pub(crate) fn run_task_with_options( } else { debug!("Ignoring Empty Task: {}", &step.name); } + + Ok(()) } fn run_task_flow( flow_info: &FlowInfo, flow_state: Rc>, execution_plan: &ExecutionPlan, -) { +) -> Result<(), CargoMakeError> { for step in &execution_plan.steps { - run_task(&flow_info, flow_state.clone(), &step); + run_task(&flow_info, flow_state.clone(), &step)?; } + Ok(()) } fn create_watch_task(task: &str, options: Option, flow_info: &FlowInfo) -> Task { @@ -560,7 +590,11 @@ fn create_watch_task(task: &str, options: Option, flow_info: & task_config } -pub(crate) fn run_flow(flow_info: &FlowInfo, flow_state: Rc>, sub_flow: bool) { +pub(crate) fn run_flow( + flow_info: &FlowInfo, + flow_state: Rc>, + sub_flow: bool, +) -> Result<(), CargoMakeError> { let allow_private = sub_flow || flow_info.allow_private; let execution_plan = create_execution_plan( @@ -571,13 +605,18 @@ pub(crate) fn run_flow(flow_info: &FlowInfo, flow_state: Rc>, allow_private, sub_flow, &flow_info.skip_tasks_pattern, - ); + )?; debug!("Created execution plan: {:#?}", &execution_plan); - run_task_flow(&flow_info, flow_state, &execution_plan); + run_task_flow(&flow_info, flow_state, &execution_plan)?; + + Ok(()) } -fn run_protected_flow(flow_info: &FlowInfo, flow_state: Rc>) { +fn run_protected_flow( + flow_info: &FlowInfo, + flow_state: Rc>, +) -> Result<(), CargoMakeError> { let proxy_task = create_proxy_task( &flow_info.task, flow_info.allow_private, @@ -586,7 +625,7 @@ fn run_protected_flow(flow_info: &FlowInfo, flow_state: Rc>) flow_info.cli_arguments.clone(), ); - let exit_code = command::run_command(&proxy_task.command.unwrap(), &proxy_task.args, false); + let exit_code = command::run_command(&proxy_task.command.unwrap(), &proxy_task.args, false)?; if exit_code != 0 { match flow_info.config.config.on_error_task { @@ -595,13 +634,14 @@ fn run_protected_flow(flow_info: &FlowInfo, flow_state: Rc>) error_flow_info.disable_on_error = true; error_flow_info.task = on_error_task.clone(); - run_flow(&error_flow_info, flow_state, false); + run_flow(&error_flow_info, flow_state, false)?; } _ => (), }; error!("Task error detected, exit code: {}", &exit_code); } + Ok(()) } /// Runs the requested tasks.
@@ -616,7 +656,7 @@ pub fn run( cli_args: &CliArgs, start_time: SystemTime, time_summary_vec: Vec<(String, u128)>, -) { +) -> Result<(), CargoMakeError> { time_summary::init(&config, &cli_args); let skip_tasks_pattern = match cli_args.skip_tasks_pattern { @@ -647,9 +687,9 @@ pub fn run( let flow_state_rc = Rc::new(RefCell::new(flow_state)); if flow_info.disable_on_error || flow_info.config.config.on_error_task.is_none() { - run_flow(&flow_info, flow_state_rc.clone(), false); + run_flow(&flow_info, flow_state_rc.clone(), false)?; } else { - run_protected_flow(&flow_info, flow_state_rc.clone()); + run_protected_flow(&flow_info, flow_state_rc.clone())?; } let time_string = match start_time.elapsed() { @@ -663,4 +703,6 @@ pub fn run( time_summary::print(&flow_state_rc.borrow().time_summary); info!("Build Done{}.", &time_string); + + Ok(()) } diff --git a/src/lib/runner_test.rs b/src/lib/runner_test.rs index 4b645a82..a93e0bf2 100755 --- a/src/lib/runner_test.rs +++ b/src/lib/runner_test.rs @@ -45,7 +45,7 @@ fn run_flow_private() { cli_arguments: None, }; - run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false).unwrap(); } #[test] @@ -82,7 +82,7 @@ fn run_flow_private_skipped() { cli_arguments: None, }; - run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false).unwrap(); } #[test] @@ -119,7 +119,7 @@ fn run_flow_private_sub_task() { cli_arguments: None, }; - run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), true); + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), true).unwrap(); } #[test] @@ -156,7 +156,7 @@ fn run_flow_allow_private() { cli_arguments: None, }; - run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false).unwrap(); } #[test] @@ -195,7 +195,7 @@ fn run_task_bad_script() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -235,7 +235,7 @@ fn run_task_script_with_args_error() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -274,7 +274,7 @@ fn run_task_script_with_args_valid() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -313,7 +313,7 @@ fn run_task_command() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -353,7 +353,7 @@ fn run_task_bad_command_valid_script() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -391,7 +391,7 @@ fn run_task_no_command_valid_script() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -438,7 +438,7 @@ fn run_task_bad_run_task_valid_command() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -482,7 +482,7 @@ fn run_task_valid_run_task() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -522,7 +522,7 @@ fn run_task_invalid_task() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -571,7 +571,7 @@ fn run_task_set_env_file() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_ENV_FILE_TEST1"), "1"); @@ -625,7 +625,7 @@ fn run_task_set_env() { envmnt::set("TEST_RUN_TASK_SET_ENV", "EMPTY"); - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); assert_eq!(envmnt::get_or_panic("TEST_RUN_TASK_SET_ENV"), "VALID"); } @@ -667,7 +667,7 @@ fn run_task_cwd_no_such_dir() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -706,7 +706,7 @@ fn run_task_cwd_dir_exists() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -745,7 +745,7 @@ fn run_task_cwd_env_expansion() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -785,7 +785,7 @@ fn run_task_deprecated_message() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -825,7 +825,7 @@ fn run_task_deprecated_flag() { config: task, }; - run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step); + run_task(&flow_info, Rc::new(RefCell::new(FlowState::new())), &step).unwrap(); } #[test] @@ -1335,7 +1335,8 @@ fn run_sub_task_and_report_for_name() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); assert!(output); } @@ -1381,7 +1382,8 @@ fn run_sub_task_and_report_for_name_not_found() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); } #[test] @@ -1429,7 +1431,8 @@ fn run_sub_task_and_report_for_details_single() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); assert!(output); } @@ -1480,7 +1483,8 @@ fn run_sub_task_and_report_for_details_multiple() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); assert!(output); } @@ -1525,7 +1529,8 @@ fn run_sub_task_and_report_routing_empty() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); assert!(!output); } @@ -1578,7 +1583,8 @@ fn run_sub_task_and_report_routing_no_condition() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); assert!(output); } @@ -1648,7 +1654,8 @@ fn run_sub_task_and_report_routing_condition_not_met() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); assert!(!output); } @@ -1702,7 +1709,8 @@ fn run_sub_task_and_report_routing_not_found() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); } #[test] @@ -1751,7 +1759,8 @@ fn run_sub_task_and_report_with_cleanup_task_but_no_fork() { &flow_info, Rc::new(RefCell::new(FlowState::new())), &sub_task, - ); + ) + .unwrap(); } #[test] @@ -1782,7 +1791,7 @@ fn get_sub_task_info_for_routing_info_empty() { }; let (task_name, fork, parallel, cleanup_task) = - get_sub_task_info_for_routing_info(&flow_info, &vec![]); + get_sub_task_info_for_routing_info(&flow_info, &vec![]).unwrap(); assert!(task_name.is_none()); assert!(!fork); @@ -1845,7 +1854,8 @@ fn get_sub_task_info_for_routing_info_condition_not_met() { condition_script: None, condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert!(task_name.is_none()); assert!(!fork); @@ -1908,7 +1918,8 @@ fn get_sub_task_info_for_routing_info_condition_found() { condition_script: None, condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test"]); assert!(!fork); @@ -1971,7 +1982,8 @@ fn get_sub_task_info_for_routing_info_condition_found_multiple_tasks() { condition_script: None, condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test1", "test2"]); assert!(!fork); @@ -2017,7 +2029,8 @@ fn get_sub_task_info_for_routing_info_script_not_met() { condition_script: Some(ConditionScriptValue::Text(vec!["exit 1".to_string()])), condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert!(task_name.is_none()); assert!(!fork); @@ -2063,7 +2076,8 @@ fn get_sub_task_info_for_routing_info_script_found() { condition_script: Some(ConditionScriptValue::Text(vec!["exit 0".to_string()])), condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test"]); assert!(!fork); @@ -2137,7 +2151,8 @@ fn get_sub_task_info_for_routing_info_multiple_found() { condition_script_runner_args: None, }, ], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test1"]); assert!(!fork); @@ -2220,7 +2235,8 @@ fn get_sub_task_info_for_routing_info_default() { condition_script_runner_args: None, }, ], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["default"]); assert!(!fork); @@ -2312,7 +2328,8 @@ fn get_sub_task_info_for_routing_info_multiple() { condition_script_runner_args: None, }, ], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test3"]); assert!(!fork); @@ -2375,7 +2392,8 @@ fn get_sub_task_info_for_routing_info_fork_false() { condition_script: None, condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test"]); assert!(!fork); @@ -2438,7 +2456,8 @@ fn get_sub_task_info_for_routing_info_fork_true() { condition_script: None, condition_script_runner_args: None, }], - ); + ) + .unwrap(); assert_eq!(task_name.unwrap(), vec!["test"]); assert!(fork); diff --git a/src/lib/scriptengine/duck_script/mod.rs b/src/lib/scriptengine/duck_script/mod.rs index 58052a09..3e153e4c 100644 --- a/src/lib/scriptengine/duck_script/mod.rs +++ b/src/lib/scriptengine/duck_script/mod.rs @@ -10,6 +10,7 @@ mod mod_test; mod sdk; use crate::environment; +use crate::error::CargoMakeError; use crate::logger::{get_level, get_log_level, LogLevel}; use crate::types::{FlowInfo, FlowState}; use duckscript::runner; @@ -25,7 +26,7 @@ pub(crate) fn execute( flow_info: Option<&FlowInfo>, flow_state: Option>>, validate: bool, -) -> bool { +) -> Result { let mut array_command = "@ = array".to_string(); let mut index = 0; for _ in cli_arguments { @@ -58,7 +59,7 @@ pub(crate) fn execute( error!("Error while running duckscript: {}", error); } - return false; + return Ok(false); } }; @@ -67,14 +68,14 @@ pub(crate) fn execute( environment::setup_cwd(Some(&directory)); } - true + Ok(true) } Err(error) => { if validate { error!("Unable to load duckscript SDK: {}", error); } - false + Ok(false) } } } diff --git a/src/lib/scriptengine/duck_script/mod_test.rs b/src/lib/scriptengine/duck_script/mod_test.rs index fd424eaa..fe08748a 100644 --- a/src/lib/scriptengine/duck_script/mod_test.rs +++ b/src/lib/scriptengine/duck_script/mod_test.rs @@ -10,7 +10,8 @@ fn execute_duckscript() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); assert!(valid); } @@ -22,7 +23,8 @@ fn execute_duckscript_error_no_validate() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), false, - ); + ) + .unwrap(); assert!(!valid); } @@ -35,7 +37,8 @@ fn execute_duckscript_error_with_validate() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); } #[test] @@ -46,7 +49,8 @@ fn execute_duckscript_cli_arguments() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); assert!(valid); } @@ -59,7 +63,8 @@ fn execute_duckscript_cli_arguments2() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); } #[test] @@ -71,7 +76,8 @@ fn execute_duckscript_crash() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); } #[test] @@ -83,7 +89,8 @@ fn execute_duckscript_crash2() { Some(&test::create_empty_flow_info()), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); } #[test] @@ -115,7 +122,8 @@ fn cm_run_task_valid() { Some(&flow_info), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); assert!(envmnt::is_equal("CM_RUN_TASK_VALID_TEST", "3")); } @@ -136,5 +144,6 @@ fn cm_run_task_error() { Some(&flow_info), Some(Rc::new(RefCell::new(FlowState::new()))), true, - ); + ) + .unwrap(); } diff --git a/src/lib/scriptengine/duck_script/sdk/cm_run_task.rs b/src/lib/scriptengine/duck_script/sdk/cm_run_task.rs index dc503b49..63b3f130 100644 --- a/src/lib/scriptengine/duck_script/sdk/cm_run_task.rs +++ b/src/lib/scriptengine/duck_script/sdk/cm_run_task.rs @@ -3,6 +3,7 @@ //! Enables to run cargo-make tasks from within duckscript. //! +use crate::error::CargoMakeError; use crate::runner; use crate::types::{FlowInfo, FlowState}; use duckscript::types::command::{Command, CommandResult}; @@ -27,7 +28,9 @@ impl Command for CommandImpl { fn run(&self, arguments: Vec) -> CommandResult { if arguments.is_empty() { - CommandResult::Error("No task name provided.".to_string()) + CommandResult::Error( + CargoMakeError::NotFound(String::from("No task name provided.")).to_string(), + ) } else { let (task_name, async_run) = if arguments.len() > 0 && arguments[0] == "--async" { (arguments[1].clone(), true) @@ -42,15 +45,18 @@ impl Command for CommandImpl { if async_run { let cloned_flow_state = self.flow_state.borrow().clone(); - thread::spawn(move || { + thread::spawn(move || -> Result<(), CargoMakeError> { runner::run_flow( &sub_flow_info, Rc::new(RefCell::new(cloned_flow_state)), true, - ); + ) }); } else { - runner::run_flow(&sub_flow_info, self.flow_state.clone(), true); + if let Err(e) = runner::run_flow(&sub_flow_info, self.flow_state.clone(), true) + { + return CommandResult::Error(e.to_string()); + } } CommandResult::Continue(Some("true".to_string())) diff --git a/src/lib/scriptengine/generic_script.rs b/src/lib/scriptengine/generic_script.rs index 3ae49202..588a5074 100644 --- a/src/lib/scriptengine/generic_script.rs +++ b/src/lib/scriptengine/generic_script.rs @@ -8,6 +8,7 @@ mod generic_script_test; use crate::command; +use crate::error::CargoMakeError; use crate::io::delete_file; use crate::scriptengine::script_utils::create_script_file; @@ -16,7 +17,7 @@ fn run_file( runner: &String, arguments: Option>, cli_arguments: &mut Vec, -) -> bool { +) -> Result { let mut args = match arguments { Some(values) => values, None => vec![], @@ -26,10 +27,10 @@ fn run_file( args.append(cli_arguments); - let exit_code = command::run_command(runner, &Some(args), false); + let exit_code = command::run_command(runner, &Some(args), false)?; debug!("Executed script, exit code: {}", exit_code); - exit_code == 0 + Ok(exit_code == 0) } pub(crate) fn execute( @@ -39,10 +40,10 @@ pub(crate) fn execute( arguments: Option>, cli_arguments: &Vec, validate: bool, -) -> bool { +) -> Result { let file = create_script_file(script_text, &extension); - let valid = run_file(&file, &runner, arguments, &mut cli_arguments.clone()); + let valid = run_file(&file, &runner, arguments, &mut cli_arguments.clone())?; delete_file(&file); @@ -50,5 +51,5 @@ pub(crate) fn execute( error!("Unable to execute script."); } - return valid; + Ok(valid) } diff --git a/src/lib/scriptengine/generic_script_test.rs b/src/lib/scriptengine/generic_script_test.rs index 9878bb49..bdef2379 100644 --- a/src/lib/scriptengine/generic_script_test.rs +++ b/src/lib/scriptengine/generic_script_test.rs @@ -10,7 +10,8 @@ fn execute_shell() { None, &vec![], true, - ); + ) + .unwrap(); assert!(valid); } @@ -24,7 +25,8 @@ fn execute_shell_error() { None, &vec![], true, - ); + ) + .unwrap(); } #[test] @@ -36,7 +38,8 @@ fn execute_shell_error_no_validate() { None, &vec![], false, - ); + ) + .unwrap(); assert!(!valid); } @@ -49,7 +52,8 @@ fn execute_shell_empty_arguments() { Some(vec![]), &vec![], true, - ); + ) + .unwrap(); assert!(valid); } @@ -63,7 +67,8 @@ fn execute_shell_cli_arguments() { Some(vec![]), &vec!["0".to_string()], true, - ); + ) + .unwrap(); assert!(valid); } @@ -78,5 +83,6 @@ fn execute_shell_cli_arguments_error() { Some(vec![]), &vec!["1".to_string()], true, - ); + ) + .unwrap(); } diff --git a/src/lib/scriptengine/mod.rs b/src/lib/scriptengine/mod.rs index f5f829df..78c85229 100755 --- a/src/lib/scriptengine/mod.rs +++ b/src/lib/scriptengine/mod.rs @@ -16,6 +16,7 @@ mod shell_to_batch; mod mod_test; use crate::environment; +use crate::error::CargoMakeError; use crate::io; use crate::toolchain; use crate::types::{FlowInfo, FlowState, ScriptValue, Task}; @@ -160,7 +161,7 @@ pub(crate) fn invoke( task: &Task, flow_info: &FlowInfo, flow_state: Rc>, -) -> bool { +) -> Result { match task.script { Some(ref script) => { let validate = !task.should_ignore_errors(); @@ -193,7 +194,7 @@ pub(crate) fn invoke( output } - None => false, + None => Ok(false), } } @@ -205,7 +206,7 @@ pub(crate) fn invoke_script_in_flow_context( validate: bool, flow_info: Option<&FlowInfo>, flow_state: Option>>, -) -> bool { +) -> Result { let cli_arguments = match flow_info { Some(info) => match info.cli_arguments { Some(ref args) => args.clone(), @@ -233,7 +234,7 @@ pub(crate) fn invoke_script_pre_flow( script_extension: Option, validate: bool, cli_arguments: &Vec, -) -> bool { +) -> Result { invoke_script( script, script_runner, @@ -255,7 +256,7 @@ fn invoke_script( flow_info: Option<&FlowInfo>, flow_state: Option>>, cli_arguments: &Vec, -) -> bool { +) -> Result { let engine_type = get_engine_type(script, &script_runner, &script_extension); match engine_type { @@ -297,6 +298,6 @@ fn invoke_script( let extension = script_extension.clone(); shebang_script::execute(&script_text, &extension, cli_arguments, validate) } - EngineType::Unsupported => false, + EngineType::Unsupported => Ok(false), } } diff --git a/src/lib/scriptengine/mod_test.rs b/src/lib/scriptengine/mod_test.rs index b34d2840..7320243c 100755 --- a/src/lib/scriptengine/mod_test.rs +++ b/src/lib/scriptengine/mod_test.rs @@ -193,7 +193,8 @@ fn invoke_no_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -206,7 +207,8 @@ fn invoke_no_script_no_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(!output); } @@ -220,7 +222,8 @@ fn invoke_no_script() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(!output); } @@ -235,7 +238,8 @@ fn invoke_os_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -251,7 +255,8 @@ fn invoke_duckscript_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -269,7 +274,8 @@ fn invoke_duckscript_runner_error() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -288,7 +294,8 @@ fn invoke_rust_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -308,7 +315,8 @@ fn invoke_rust_runner_error() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -324,7 +332,8 @@ fn invoke_shell_to_batch_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -340,7 +349,8 @@ fn invoke_shell_to_batch_runner_error() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -356,7 +366,8 @@ fn invoke_generic_runner() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } @@ -373,7 +384,8 @@ fn invoke_generic_runner_error() { &task, &test::create_empty_flow_info(), Rc::new(RefCell::new(FlowState::new())), - ); + ) + .unwrap(); assert!(output); } diff --git a/src/lib/scriptengine/os_script.rs b/src/lib/scriptengine/os_script.rs index 205b5924..8019bfbf 100644 --- a/src/lib/scriptengine/os_script.rs +++ b/src/lib/scriptengine/os_script.rs @@ -8,14 +8,15 @@ mod os_script_test; use crate::command; +use crate::error::CargoMakeError; pub(crate) fn execute( script_text: &Vec, runner: Option, cli_arguments: &Vec, validate: bool, -) -> bool { +) -> Result { let exit_code = - command::run_script_get_exit_code(&script_text, runner, &cli_arguments, validate); - exit_code == 0 + command::run_script_get_exit_code(&script_text, runner, &cli_arguments, validate)?; + Ok(exit_code == 0) } diff --git a/src/lib/scriptengine/os_script_test.rs b/src/lib/scriptengine/os_script_test.rs index b61dd80a..9b06f64c 100644 --- a/src/lib/scriptengine/os_script_test.rs +++ b/src/lib/scriptengine/os_script_test.rs @@ -3,7 +3,7 @@ use crate::test; #[test] fn execute_shell() { - execute(&vec!["exit 0".to_string()], None, &vec![], true); + execute(&vec!["exit 0".to_string()], None, &vec![], true).unwrap(); } #[test] @@ -13,18 +13,19 @@ fn execute_shell_with_runner() { Some(test::get_os_runner()), &vec![], true, - ); + ) + .unwrap(); assert!(valid); } #[test] #[should_panic] fn execute_shell_error() { - execute(&vec!["exit 1".to_string()], None, &vec![], true); + execute(&vec!["exit 1".to_string()], None, &vec![], true).unwrap(); } #[test] fn execute_shell_error_no_validate() { - let valid = execute(&vec!["exit 1".to_string()], None, &vec![], false); + let valid = execute(&vec!["exit 1".to_string()], None, &vec![], false).unwrap(); assert!(!valid); } diff --git a/src/lib/scriptengine/rsscript.rs b/src/lib/scriptengine/rsscript.rs index df81baf8..0ab2c4c6 100755 --- a/src/lib/scriptengine/rsscript.rs +++ b/src/lib/scriptengine/rsscript.rs @@ -8,6 +8,7 @@ mod rsscript_test; use crate::command; +use crate::error::CargoMakeError; use crate::installer::{cargo_plugin_installer, crate_installer}; use crate::scriptengine::script_utils::create_persisted_script_file; use crate::types::{InstallCrateInfo, TestArg}; @@ -30,7 +31,7 @@ fn get_script_runner() -> ScriptRunner { } } -fn install_crate(provider: &ScriptRunner) { +fn install_crate(provider: &ScriptRunner) -> Result<(), CargoMakeError> { // install dependencies match provider { ScriptRunner::RustScript => { @@ -47,7 +48,7 @@ fn install_crate(provider: &ScriptRunner) { force: None, }; - crate_installer::install(&None, &info, &None, false); + crate_installer::install(&None, &info, &None, false)?; } ScriptRunner::CargoScript => cargo_plugin_installer::install_crate( &None, @@ -58,7 +59,7 @@ fn install_crate(provider: &ScriptRunner) { &None, &None, &None, - ), + )?, ScriptRunner::CargoPlay => cargo_plugin_installer::install_crate( &None, Some("play"), @@ -68,8 +69,9 @@ fn install_crate(provider: &ScriptRunner) { &None, &None, &None, - ), + )?, }; + Ok(()) } fn create_rust_file(rust_script: &Vec) -> String { @@ -81,7 +83,7 @@ fn run_file( runner_arguments: Option>, cli_arguments: &Vec, provider: &ScriptRunner, -) -> bool { +) -> Result { let (use_cargo, command) = match provider { ScriptRunner::RustScript => (false, "rust-script"), ScriptRunner::CargoScript => (true, "script"), @@ -103,10 +105,10 @@ fn run_file( command::run_command("cargo", &Some(args), false) } else { command::run_command(command, &Some(args), false) - }; + }?; debug!("Executed rust code, exit code: {}", exit_code); - exit_code == 0 + Ok(exit_code == 0) } pub(crate) fn execute( @@ -114,18 +116,18 @@ pub(crate) fn execute( runner_arguments: Option>, cli_arguments: &Vec, validate: bool, -) -> bool { +) -> Result { let provider = get_script_runner(); - install_crate(&provider); + install_crate(&provider)?; let file = create_rust_file(rust_script); - let valid = run_file(&file, runner_arguments, &cli_arguments, &provider); + let valid = run_file(&file, runner_arguments, &cli_arguments, &provider)?; if validate && !valid { error!("Unable to execute rust code."); } - return valid; + Ok(valid) } diff --git a/src/lib/scriptengine/rsscript_test.rs b/src/lib/scriptengine/rsscript_test.rs index 252fa4a6..71009e94 100755 --- a/src/lib/scriptengine/rsscript_test.rs +++ b/src/lib/scriptengine/rsscript_test.rs @@ -61,7 +61,8 @@ fn execute_default_valid() { None, &vec![], true, - ); + ) + .unwrap(); assert!(valid); } } @@ -78,7 +79,8 @@ fn execute_default_not_compile() { None, &vec![], true, - ); + ) + .unwrap(); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -96,7 +98,8 @@ fn execute_default_runtime_panic() { None, &vec![], true, - ); + ) + .unwrap(); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -113,7 +116,8 @@ fn execute_default_runtime_panic_no_validate() { None, &vec![], false, - ); + ) + .unwrap(); assert!(!valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); @@ -131,7 +135,8 @@ fn execute_rust_script_valid() { None, &vec![], true, - ); + ) + .unwrap(); assert!(valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); @@ -150,7 +155,8 @@ fn execute_rust_script_not_compile() { None, &vec![], true, - ); + ) + .unwrap(); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -168,7 +174,8 @@ fn execute_rust_script_runtime_panic() { None, &vec![], true, - ); + ) + .unwrap(); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -185,7 +192,8 @@ fn execute_rust_script_runtime_panic_no_validate() { None, &vec![], false, - ); + ) + .unwrap(); assert!(!valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); @@ -204,7 +212,8 @@ fn execute_cargo_play_not_compile() { None, &vec![], true, - ); + ) + .unwrap(); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -222,7 +231,8 @@ fn execute_cargo_play_runtime_panic() { None, &vec![], true, - ); + ) + .unwrap(); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); } @@ -239,7 +249,8 @@ fn execute_cargo_play_runtime_panic_no_validate() { None, &vec![], false, - ); + ) + .unwrap(); assert!(!valid); envmnt::remove("CARGO_MAKE_RUST_SCRIPT_PROVIDER"); diff --git a/src/lib/scriptengine/shebang_script.rs b/src/lib/scriptengine/shebang_script.rs index 5f75e579..0e1a9716 100644 --- a/src/lib/scriptengine/shebang_script.rs +++ b/src/lib/scriptengine/shebang_script.rs @@ -7,6 +7,7 @@ #[path = "shebang_script_test.rs"] mod shebang_script_test; +use crate::error::CargoMakeError; use crate::scriptengine::generic_script; use std::path::Path; @@ -105,7 +106,7 @@ pub(crate) fn execute( extension: &Option, cli_arguments: &Vec, validate: bool, -) -> bool { +) -> Result { let shebang = get_shebang(&script_text); match shebang.runner { @@ -129,7 +130,7 @@ pub(crate) fn execute( error!("Unable to execute script using shebang."); } - false + Ok(false) } } } diff --git a/src/lib/scriptengine/shebang_script_test.rs b/src/lib/scriptengine/shebang_script_test.rs index 92050b6d..8fb34f30 100644 --- a/src/lib/scriptengine/shebang_script_test.rs +++ b/src/lib/scriptengine/shebang_script_test.rs @@ -91,7 +91,8 @@ fn execute_sh() { &None, &vec!["0".to_string()], true, - ); + ) + .unwrap(); assert!(valid); } @@ -104,7 +105,8 @@ fn execute_sh_error() { &None, &vec!["1".to_string()], true, - ); + ) + .unwrap(); } #[test] diff --git a/src/lib/scriptengine/shell_to_batch.rs b/src/lib/scriptengine/shell_to_batch.rs index e112afc8..7870d271 100755 --- a/src/lib/scriptengine/shell_to_batch.rs +++ b/src/lib/scriptengine/shell_to_batch.rs @@ -8,8 +8,13 @@ mod shell_to_batch_test; use crate::command; +use crate::error::CargoMakeError; -pub(crate) fn execute(script: &Vec, cli_arguments: &Vec, validate: bool) -> bool { +pub(crate) fn execute( + script: &Vec, + cli_arguments: &Vec, + validate: bool, +) -> Result { let exit_code = if cfg!(windows) { let shell_script = script.join("\n"); let windows_batch = shell2batch::convert(&shell_script); @@ -22,7 +27,7 @@ pub(crate) fn execute(script: &Vec, cli_arguments: &Vec, validat command::run_script_get_exit_code(&windows_script_lines, None, cli_arguments, validate) } else { command::run_script_get_exit_code(script, None, cli_arguments, validate) - }; + }?; - exit_code == 0 + Ok(exit_code == 0) } diff --git a/src/lib/scriptengine/shell_to_batch_test.rs b/src/lib/scriptengine/shell_to_batch_test.rs index 5f0f129a..b2fe9aec 100755 --- a/src/lib/scriptengine/shell_to_batch_test.rs +++ b/src/lib/scriptengine/shell_to_batch_test.rs @@ -6,7 +6,8 @@ fn execute_valid() { &vec!["echo test".to_string()], &vec!["test".to_string()], true, - ); + ) + .unwrap(); assert!(valid); } @@ -14,11 +15,11 @@ fn execute_valid() { #[test] #[should_panic] fn execute_error() { - execute(&vec!["exit 1".to_string()], &vec![], true); + execute(&vec!["exit 1".to_string()], &vec![], true).unwrap(); } #[test] fn execute_error_no_validate() { - let valid = execute(&vec!["exit 1".to_string()], &vec![], false); + let valid = execute(&vec!["exit 1".to_string()], &vec![], false).unwrap(); assert!(!valid); } diff --git a/src/lib/types.rs b/src/lib/types.rs index 4bfd5f43..ffa61a6e 100755 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -2459,3 +2459,10 @@ pub fn either_to_result(either: Either) -> Result { Either::Right(rhs) => Err(rhs), } } + +pub fn result_to_either(result: Result) -> Either { + match result { + Ok(lhs) => Either::Left(lhs), + Err(rhs) => Either::Right(rhs), + } +} diff --git a/src/main.rs b/src/main.rs index 4eb6a67f..3c2e7a5c 100755 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,8 @@ //! [Apache 2](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) open source license. //! +use cli::error::SuccessOrCargoMakeError; + #[cfg(test)] #[path = "main_test.rs"] mod main_test; @@ -33,9 +35,10 @@ fn get_name() -> String { "make".to_string() } -fn main() -> std::process::ExitCode { +fn main() -> SuccessOrCargoMakeError { let name = get_name(); - cli::run_cli(name, true) - .right() - .unwrap_or(std::process::ExitCode::SUCCESS) + match cli::run_cli(name, true) { + Ok(_) => Ok(std::process::ExitCode::SUCCESS).into(), + Err(e) => SuccessOrCargoMakeError::Err(e), + } } diff --git a/src/makers.rs b/src/makers.rs index 7b6308c3..c2f1a2cb 100644 --- a/src/makers.rs +++ b/src/makers.rs @@ -12,6 +12,8 @@ //! [Apache 2](https://github.com/sagiegurari/cargo-make/blob/master/LICENSE) open source license. //! +use cli::error::SuccessOrCargoMakeError; + #[cfg(test)] #[path = "makers_test.rs"] mod makers_test; @@ -20,11 +22,12 @@ fn get_name() -> String { "makers".to_string() } -fn main() -> std::process::ExitCode { +fn main() -> SuccessOrCargoMakeError { #[cfg(windows)] let _ = nu_ansi_term::enable_ansi_support(); let name = get_name(); - cli::run_cli(name, false) - .right() - .unwrap_or(std::process::ExitCode::SUCCESS) + match cli::run_cli(name, false) { + Ok(_) => Ok(std::process::ExitCode::SUCCESS).into(), + Err(e) => SuccessOrCargoMakeError::Err(e), + } } From 8bd60c7dd7c26fa0f944206ff190bfb594bea01f Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 12 Jul 2024 22:07:11 -0400 Subject: [PATCH 09/21] Rewrite remaining `panic!` to percolate `Result<_, CargoMakeError>` throughout --- src/lib/cli.rs | 13 ++---- src/lib/cli_commands/diff_steps.rs | 4 +- src/lib/cli_commands/list_steps_test.rs | 2 +- src/lib/descriptor/cargo_alias.rs | 9 ++-- src/lib/descriptor/cargo_alias_test.rs | 8 ++-- src/lib/descriptor/descriptor_deserializer.rs | 30 ++++++++----- .../descriptor_deserializer_test.rs | 15 ++++--- src/lib/descriptor/makefiles/mod_test.rs | 18 ++++---- src/lib/descriptor/mod.rs | 28 +++++++----- src/lib/descriptor/mod_test.rs | 25 ++++++----- src/lib/environment/crateinfo.rs | 24 ++++------ src/lib/environment/crateinfo_test.rs | 5 ++- src/lib/environment/mod.rs | 16 ++++--- src/lib/environment/mod_test.rs | 20 ++++----- src/lib/error.rs | 26 ++++++++++- src/lib/execution_plan.rs | 19 +++++--- src/lib/execution_plan_test.rs | 4 +- src/lib/functions/mod.rs | 40 ++++++++++------- src/lib/functions/mod_test.rs | 28 +++++++----- src/lib/functions/trim_func.rs | 14 +++--- src/lib/functions/trim_func_test.rs | 20 ++++----- src/lib/installer/mod.rs | 8 +++- src/lib/io.rs | 20 ++++----- src/lib/io_test.rs | 6 +-- .../sdk/cm_plugin_force_plugin_set_test.rs | 2 +- src/lib/runner.rs | 2 +- src/lib/scriptengine/generic_script.rs | 2 +- src/lib/scriptengine/mod.rs | 44 +++++++++---------- src/lib/scriptengine/mod_test.rs | 42 +++++++++++++----- src/lib/scriptengine/rsscript.rs | 4 +- src/lib/scriptengine/script_utils.rs | 37 +++++++--------- src/lib/scriptengine/script_utils_test.rs | 12 +++-- 32 files changed, 312 insertions(+), 235 deletions(-) diff --git a/src/lib/cli.rs b/src/lib/cli.rs index b4768fb2..dfa6c3a5 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -96,15 +96,8 @@ pub fn run(cli_args: &CliArgs, global_config: &GlobalConfig) -> Result<(), Cargo let env = cli_args.env.clone(); let experimental = cli_args.experimental; - let descriptor_load_result = descriptor::load(&build_file, force_makefile, env, experimental); - - let config = match descriptor_load_result { - Ok(config) => config, - Err(ref error) => { - error!("{}", error); - panic!("{}", error); - } - }; + let config = descriptor::load(&build_file, force_makefile, env, experimental)?; + let mut time_summary_vec = vec![]; time_summary::add( &mut time_summary_vec, @@ -141,7 +134,7 @@ pub fn run(cli_args: &CliArgs, global_config: &GlobalConfig) -> Result<(), Cargo cli_args.hide_uninteresting, ) } else if cli_args.diff_execution_plan { - let default_config = descriptor::load_internal_descriptors(true, experimental, None); + let default_config = descriptor::load_internal_descriptors(true, experimental, None)?; cli_commands::diff_steps::run( &default_config, &config, diff --git a/src/lib/cli_commands/diff_steps.rs b/src/lib/cli_commands/diff_steps.rs index ecf31d9e..f2b0c21b 100644 --- a/src/lib/cli_commands/diff_steps.rs +++ b/src/lib/cli_commands/diff_steps.rs @@ -64,11 +64,11 @@ pub(crate) fn run( let internal_file = create_file( &move |file: &mut File| write_as_string(&internal_execution_plan, &file), "toml", - ); + )?; let external_file = create_file( &move |file: &mut File| write_as_string(&external_execution_plan, &file), "toml", - ); + )?; info!("Printing diff..."); command::run_command( diff --git a/src/lib/cli_commands/list_steps_test.rs b/src/lib/cli_commands/list_steps_test.rs index 1ddbb4a2..4432c4b6 100644 --- a/src/lib/cli_commands/list_steps_test.rs +++ b/src/lib/cli_commands/list_steps_test.rs @@ -27,7 +27,7 @@ fn check( let mut path = PathBuf::new(); path.push(&file); - let actual = io::read_text_file(&path); + let actual = io::read_text_file(&path).unwrap(); io::delete_file(&file); expect.assert_eq(&actual); diff --git a/src/lib/descriptor/cargo_alias.rs b/src/lib/descriptor/cargo_alias.rs index e7a5653d..a18402d1 100644 --- a/src/lib/descriptor/cargo_alias.rs +++ b/src/lib/descriptor/cargo_alias.rs @@ -7,6 +7,7 @@ #[path = "cargo_alias_test.rs"] mod cargo_alias_test; +use crate::error::CargoMakeError; use crate::io; use crate::types::{InstallCrate, Task}; use std::collections::HashMap; @@ -24,13 +25,13 @@ struct CargoConfig { alias: Option>, } -fn load_from_file(file: &str) -> Vec<(String, Task)> { +fn load_from_file(file: &str) -> Result, CargoMakeError> { let file_path = Path::new(file); let mut tasks = vec![]; if file_path.exists() { if file_path.is_file() { - let text = io::read_text_file(&file_path.to_path_buf()); + let text = io::read_text_file(&file_path.to_path_buf())?; if !text.is_empty() { let cargo_config: CargoConfig = match toml::from_str(&text) { @@ -57,9 +58,9 @@ fn load_from_file(file: &str) -> Vec<(String, Task)> { } } - tasks + Ok(tasks) } -pub(crate) fn load() -> Vec<(String, Task)> { +pub(crate) fn load() -> Result, CargoMakeError> { load_from_file("./.cargo/config.toml") } diff --git a/src/lib/descriptor/cargo_alias_test.rs b/src/lib/descriptor/cargo_alias_test.rs index 6eb05f08..0a258043 100644 --- a/src/lib/descriptor/cargo_alias_test.rs +++ b/src/lib/descriptor/cargo_alias_test.rs @@ -2,28 +2,28 @@ use super::*; #[test] fn load_from_file_no_file() { - let tasks = load_from_file("./badfile.toml"); + let tasks = load_from_file("./badfile.toml").unwrap(); assert!(tasks.is_empty()); } #[test] fn load_from_file_parse_error() { - let tasks = load_from_file("./src/lib/test/cargo/invalid_config.toml"); + let tasks = load_from_file("./src/lib/test/cargo/invalid_config.toml").unwrap(); assert!(tasks.is_empty()); } #[test] fn load_from_file_no_alias_data() { - let tasks = load_from_file("./Cargo.toml"); + let tasks = load_from_file("./Cargo.toml").unwrap(); assert!(tasks.is_empty()); } #[test] fn load_from_file_aliases_found() { - let tasks = load_from_file("./src/lib/test/cargo/config.toml"); + let tasks = load_from_file("./src/lib/test/cargo/config.toml").unwrap(); assert_eq!(tasks.len(), 4); diff --git a/src/lib/descriptor/descriptor_deserializer.rs b/src/lib/descriptor/descriptor_deserializer.rs index b7bf4a65..02d741a8 100644 --- a/src/lib/descriptor/descriptor_deserializer.rs +++ b/src/lib/descriptor/descriptor_deserializer.rs @@ -6,9 +6,13 @@ #[path = "descriptor_deserializer_test.rs"] mod descriptor_deserializer_test; +use crate::error::CargoMakeError; use crate::types::{Config, ExternalConfig}; -pub(crate) fn load_config(descriptor_string: &str, validate: bool) -> Config { +pub(crate) fn load_config( + descriptor_string: &str, + validate: bool, +) -> Result { let config: Config = if validate { let deserializer = toml::de::Deserializer::new(descriptor_string); @@ -18,7 +22,7 @@ pub(crate) fn load_config(descriptor_string: &str, validate: bool) -> Config { Ok(value) => value, Err(error) => { error!("Unable to parse internal descriptor: {}", error); - panic!("Unable to parse internal descriptor: {}", error); + return Err(CargoMakeError::DescriptorParseFailed(error.to_string())); } } } else { @@ -26,26 +30,30 @@ pub(crate) fn load_config(descriptor_string: &str, validate: bool) -> Config { Ok(value) => value, Err(error) => { error!("Unable to parse internal descriptor: {}", error); - panic!("Unable to parse internal descriptor: {}", error); + return Err(CargoMakeError::DescriptorParseFailed(error.to_string())); } } }; - config + Ok(config) } -pub(crate) fn load_external_config(descriptor_string: &str, file: &str) -> ExternalConfig { +pub(crate) fn load_external_config( + descriptor_string: &str, + file: &str, +) -> Result { let deserializer = toml::de::Deserializer::new(descriptor_string); - let config: ExternalConfig = match serde_ignored::deserialize(deserializer, |path| { + match serde_ignored::deserialize(deserializer, |path| { warn!("Found unknown key: {} in file: {}", path, file); }) { - Ok(value) => value, + Ok(value) => Ok(value), Err(error) => { error!("Unable to parse external file: {:#?}, {}", &file, error); - panic!("Unable to parse external file: {:#?}, {}", &file, error); + return Err(CargoMakeError::ParseFileFailed( + String::from(file), + error.to_string(), + )); } - }; - - config + } } diff --git a/src/lib/descriptor/descriptor_deserializer_test.rs b/src/lib/descriptor/descriptor_deserializer_test.rs index f61d2494..6e6a67b6 100644 --- a/src/lib/descriptor/descriptor_deserializer_test.rs +++ b/src/lib/descriptor/descriptor_deserializer_test.rs @@ -3,17 +3,17 @@ use crate::descriptor::makefiles; #[test] fn load_config_base() { - load_config(makefiles::BASE, true); + load_config(makefiles::BASE, true).unwrap(); } #[test] fn load_config_stable() { - load_config(makefiles::STABLE, true); + load_config(makefiles::STABLE, true).unwrap(); } #[test] fn load_config_beta() { - load_config(makefiles::BETA, true); + load_config(makefiles::BETA, true).unwrap(); } #[test] @@ -35,7 +35,8 @@ description = "Empty Task" category2 = "Tools" "#, true, - ); + ) + .unwrap(); } #[test] @@ -56,7 +57,8 @@ description = "Empty Task" category2 = "Tools" "#, false, - ); + ) + .unwrap(); assert!(config.tasks.contains_key("empty")); } @@ -70,7 +72,8 @@ description = "Empty Task" category2 = "Tools" "#, "somefile", - ); + ) + .unwrap(); assert!(config.tasks.unwrap().contains_key("empty")); } diff --git a/src/lib/descriptor/makefiles/mod_test.rs b/src/lib/descriptor/makefiles/mod_test.rs index a4c950a9..7edd059a 100644 --- a/src/lib/descriptor/makefiles/mod_test.rs +++ b/src/lib/descriptor/makefiles/mod_test.rs @@ -1,5 +1,6 @@ use crate::condition; use crate::descriptor; +use crate::error::CargoMakeError; use crate::runner; use crate::scriptengine; use crate::scriptengine::EngineType; @@ -10,7 +11,7 @@ use rust_info::types::RustInfo; use std::cell::RefCell; use std::rc::Rc; -fn load_descriptor() -> Config { +fn load_descriptor() -> Result { descriptor::load_internal_descriptors(true, false, None) } @@ -42,7 +43,7 @@ fn create_flow_info(config: &Config) -> FlowInfo { fn makefile_task_condition_test(name: &str, expect_enabled: bool, linux_only: bool, ci_only: bool) { if !linux_only || test::is_linux() { - let config = load_descriptor(); + let config = load_descriptor().unwrap(); let task = get_task(name, &config); let flow_info = create_flow_info(&config); let step = Step { @@ -75,14 +76,15 @@ fn makefile_task_disabled_test(name: &str, linux_only: bool) { } fn makefile_task_script_engine_test(name: &str, engine: EngineType) { - let config = load_descriptor(); + let config = load_descriptor().unwrap(); let task = get_task(name, &config); let output = scriptengine::get_engine_type( &task.script.unwrap(), &task.script_runner, &task.script_extension, - ); + ) + .unwrap(); assert_eq!(output, engine); } @@ -90,7 +92,7 @@ fn makefile_task_script_engine_test(name: &str, engine: EngineType) { #[test] fn makefile_coverage_test() { if test::is_linux() { - let config = load_descriptor(); + let config = load_descriptor().unwrap(); let task = get_task("coverage", &config); let run_task_info = task.run_task.unwrap(); @@ -167,7 +169,7 @@ fn makefile_build_file_increment_no_file_test() { let name = "build-file-increment"; - let config = load_descriptor(); + let config = load_descriptor().unwrap(); let task = get_task(name, &config); let flow_info = create_flow_info(&config); @@ -199,7 +201,7 @@ fn makefile_build_file_increment_file_exists_test() { let name = "build-file-increment"; - let config = load_descriptor(); + let config = load_descriptor().unwrap(); let task = get_task(name, &config); let flow_info = create_flow_info(&config); @@ -236,7 +238,7 @@ fn makefile_build_file_increment_panic_invalid_data_test() { let name = "build-file-increment"; - let config = load_descriptor(); + let config = load_descriptor().unwrap(); let task = get_task(name, &config); let flow_info = create_flow_info(&config); diff --git a/src/lib/descriptor/mod.rs b/src/lib/descriptor/mod.rs index d6ff1780..0a84fe4b 100755 --- a/src/lib/descriptor/mod.rs +++ b/src/lib/descriptor/mod.rs @@ -318,12 +318,12 @@ fn load_external_descriptor( envmnt::set("CARGO_MAKE_MAKEFILE_PATH", &absolute_file_path); } - let external_descriptor = io::read_text_file(&file_path); + let external_descriptor = io::read_text_file(&file_path)?; check_makefile_min_version(&external_descriptor)?; let mut file_config = - descriptor_deserializer::load_external_config(&external_descriptor, &file_path_string); + descriptor_deserializer::load_external_config(&external_descriptor, &file_path_string)?; debug!("Loaded external config: {:#?}", &file_config); file_config = add_file_location_info(file_config, &absolute_file_path); @@ -349,7 +349,10 @@ fn load_external_descriptor( } } else if force { error!("Descriptor file: {:#?} not found.", &file_path); - panic!("Descriptor file: {:#?} not found.", &file_path); + Err(CargoMakeError::NotFound(format!( + "Descriptor file: {:#?} not found.", + &file_path + ))) } else { debug!("External file not found or is not a file, skipping."); @@ -361,7 +364,7 @@ pub(crate) fn load_internal_descriptors( stable: bool, experimental: bool, modify_config: Option, -) -> Config { +) -> Result { debug!("Loading base tasks."); let base_descriptor = if stable { @@ -370,7 +373,7 @@ pub(crate) fn load_internal_descriptors( makefiles::BASE }; - let mut base_config = descriptor_deserializer::load_config(&base_descriptor, false); + let mut base_config = descriptor_deserializer::load_config(&base_descriptor, false)?; debug!("Loaded base config: {:#?}", &base_config); if experimental { @@ -378,7 +381,7 @@ pub(crate) fn load_internal_descriptors( let experimental_descriptor = makefiles::BETA; let experimental_config = - descriptor_deserializer::load_config(&experimental_descriptor, false); + descriptor_deserializer::load_config(&experimental_descriptor, false)?; debug!("Loaded experimental config: {:#?}", &experimental_config); let mut base_tasks = base_config.tasks; @@ -409,7 +412,7 @@ pub(crate) fn load_internal_descriptors( None => (), }; - base_config + Ok(base_config) } fn merge_base_config_and_external_config( @@ -510,7 +513,7 @@ fn load_descriptors( experimental: bool, modify_core_tasks: Option, ) -> Result { - let default_config = load_internal_descriptors(stable, experimental, modify_core_tasks); + let default_config = load_internal_descriptors(stable, experimental, modify_core_tasks)?; let mut external_config = load_external_descriptor(".", file_name, force, true)?; @@ -551,10 +554,10 @@ fn load_descriptors( Ok(config) } -fn load_cargo_aliases(config: &mut Config) { +fn load_cargo_aliases(config: &mut Config) -> Result<(), CargoMakeError> { if let Some(load_cargo_aliases) = config.config.load_cargo_aliases { if load_cargo_aliases { - let alias_tasks = cargo_alias::load(); + let alias_tasks = cargo_alias::load()?; for (name, task) in alias_tasks { match config.tasks.get(&name) { None => { @@ -566,6 +569,7 @@ fn load_cargo_aliases(config: &mut Config) { } } } + Ok(()) } /// Loads the tasks descriptor.
@@ -603,7 +607,7 @@ pub fn load( } } None => { - let core_config = load_internal_descriptors(true, experimental, modify_core_tasks); + let core_config = load_internal_descriptors(true, experimental, modify_core_tasks)?; let external_config = ExternalConfig { extend: None, config: Some(config.config), @@ -624,7 +628,7 @@ pub fn load( }; } - load_cargo_aliases(&mut config); + load_cargo_aliases(&mut config)?; if let Some(unstable_features) = &config.config.unstable_features { for feature in unstable_features { diff --git a/src/lib/descriptor/mod_test.rs b/src/lib/descriptor/mod_test.rs index dc556111..40bd9e0c 100755 --- a/src/lib/descriptor/mod_test.rs +++ b/src/lib/descriptor/mod_test.rs @@ -387,7 +387,7 @@ fn load_not_found() { #[test] fn load_internal_descriptors_no_stable() { - let config = load_internal_descriptors(false, false, None); + let config = load_internal_descriptors(false, false, None).unwrap(); let mut task = config.tasks.get("empty"); assert!(task.is_some()); @@ -397,7 +397,7 @@ fn load_internal_descriptors_no_stable() { #[test] fn load_internal_descriptors_with_stable() { - let config = load_internal_descriptors(true, false, None); + let config = load_internal_descriptors(true, false, None).unwrap(); let mut task = config.tasks.get("empty"); assert!(task.is_some()); @@ -407,7 +407,7 @@ fn load_internal_descriptors_with_stable() { #[test] fn load_internal_descriptors_no_experimental() { - let config = load_internal_descriptors(true, false, None); + let config = load_internal_descriptors(true, false, None).unwrap(); let mut task = config.tasks.get("ci-flow"); assert!(task.is_some()); @@ -417,7 +417,7 @@ fn load_internal_descriptors_no_experimental() { #[test] fn load_internal_descriptors_with_experimental() { - let config = load_internal_descriptors(true, true, None); + let config = load_internal_descriptors(true, true, None).unwrap(); let mut task = config.tasks.get("ci-flow"); assert!(task.is_some()); @@ -434,7 +434,8 @@ fn load_internal_descriptors_modify_empty() { private: None, namespace: None, }), - ); + ) + .unwrap(); let mut task = config.tasks.get("empty"); assert!(task.is_some()); @@ -453,7 +454,8 @@ fn load_internal_descriptors_modify_private() { private: Some(true), namespace: None, }), - ); + ) + .unwrap(); let mut task = config.tasks.get("empty"); assert!(task.is_some()); @@ -472,7 +474,8 @@ fn load_internal_descriptors_modify_namespace() { private: None, namespace: Some("default".to_string()), }), - ); + ) + .unwrap(); let mut task = config.tasks.get("empty"); assert!(task.is_none()); @@ -950,10 +953,10 @@ fn check_makefile_min_version_same_min_version() { #[test] fn load_cargo_aliases_no_file() { - let mut config = load_internal_descriptors(false, false, None); + let mut config = load_internal_descriptors(false, false, None).unwrap(); let count = config.tasks.len(); - load_cargo_aliases(&mut config); + load_cargo_aliases(&mut config).unwrap(); assert_eq!(count, config.tasks.len()); } @@ -961,11 +964,11 @@ fn load_cargo_aliases_no_file() { #[test] #[ignore] fn load_cargo_aliases_found() { - let mut config = load_internal_descriptors(false, false, None); + let mut config = load_internal_descriptors(false, false, None).unwrap(); let count = config.tasks.len(); setup_cwd(Some("src/lib/test/workspace1/member1")); - load_cargo_aliases(&mut config); + load_cargo_aliases(&mut config).unwrap(); setup_cwd(Some("../../../../..")); assert_eq!(count, config.tasks.len()); diff --git a/src/lib/environment/crateinfo.rs b/src/lib/environment/crateinfo.rs index 9dbc7b9f..533b704f 100755 --- a/src/lib/environment/crateinfo.rs +++ b/src/lib/environment/crateinfo.rs @@ -7,6 +7,7 @@ #[path = "crateinfo_test.rs"] mod crateinfo_test; +use crate::error::CargoMakeError; use crate::types::{CrateDependency, CrateInfo, PackageInfo, Workspace}; use cargo_metadata::camino::Utf8PathBuf; use cargo_metadata::{Metadata, MetadataCommand}; @@ -267,11 +268,11 @@ fn load_workspace_members(crate_info: &mut CrateInfo) { } /// Loads the crate info based on the Cargo.toml found in the current working directory. -pub(crate) fn load() -> CrateInfo { +pub(crate) fn load() -> Result { load_from(Path::new("Cargo.toml").to_path_buf()) } -pub(crate) fn load_from(file_path: PathBuf) -> CrateInfo { +pub(crate) fn load_from(file_path: PathBuf) -> Result { if file_path.exists() { info!("Calling cargo metadata to extract project info"); @@ -282,10 +283,7 @@ pub(crate) fn load_from(file_path: PathBuf) -> CrateInfo { let mut crate_info = convert_metadata_to_crate_info(&metadata); debug!("Reading file: {:#?}", &file_path); - let crate_info_string = match fsio::file::read_text_file(&file_path) { - Ok(content) => content, - Err(error) => panic!("Unable to open Cargo.toml, error: {}", error), - }; + let crate_info_string = fsio::file::read_text_file(&file_path)?; let crate_info_deserialized: CrateInfoMinimal = match toml::from_str(&crate_info_string) { @@ -302,7 +300,7 @@ pub(crate) fn load_from(file_path: PathBuf) -> CrateInfo { debug!("Loaded Cargo.toml: {:#?}", &crate_info); - crate_info + Ok(crate_info) } Err(error) => { warn!( @@ -310,19 +308,13 @@ pub(crate) fn load_from(file_path: PathBuf) -> CrateInfo { error ); - let crate_info_string = match fsio::file::read_text_file(&file_path) { - Ok(content) => content, - Err(error) => panic!("Unable to open Cargo.toml, error: {}", error), - }; + let crate_info_string = fsio::file::read_text_file(&file_path)?; - match toml::from_str(&crate_info_string) { - Ok(value) => value, - Err(error) => panic!("Unable to parse Cargo.toml, {}", error), - } + toml::from_str(&crate_info_string).map_err(From::from) } } } else { - CrateInfo::new() + Ok(CrateInfo::new()) } } diff --git a/src/lib/environment/crateinfo_test.rs b/src/lib/environment/crateinfo_test.rs index d58d4d7e..f832a684 100755 --- a/src/lib/environment/crateinfo_test.rs +++ b/src/lib/environment/crateinfo_test.rs @@ -5,7 +5,7 @@ use cargo_metadata::camino::Utf8Path; #[test] fn crate_info_load() { - let crate_info = load(); + let crate_info = load().unwrap(); assert!(crate_info.package.is_some()); assert!(crate_info.workspace.is_none()); @@ -787,7 +787,8 @@ fn get_crate_target_dir() { fn load_from_inherit_from_workspace_toml() { if is_min_rust_version("1.64.0") { let crate_info = - load_from(Path::new("src/lib/test/workspace-inherit/member1/Cargo.toml").to_path_buf()); + load_from(Path::new("src/lib/test/workspace-inherit/member1/Cargo.toml").to_path_buf()) + .unwrap(); let package_info = crate_info.package.unwrap(); assert_eq!(package_info.name.unwrap(), "member1"); diff --git a/src/lib/environment/mod.rs b/src/lib/environment/mod.rs index 60d2e95b..3deb8c62 100644 --- a/src/lib/environment/mod.rs +++ b/src/lib/environment/mod.rs @@ -352,8 +352,8 @@ fn setup_env_for_duckscript() { envmnt::set("CARGO_MAKE_DUCKSCRIPT_SDK_VERSION", version); } -fn setup_env_for_crate(home: Option) -> CrateInfo { - let crate_info = crateinfo::load(); +fn setup_env_for_crate(home: Option) -> Result { + let crate_info = crateinfo::load()?; let crate_info_clone = crate_info.clone(); let package_info = crate_info.package.unwrap_or(PackageInfo::new()); @@ -436,7 +436,7 @@ fn setup_env_for_crate(home: Option) -> CrateInfo { ), } - crate_info_clone + Ok(crate_info_clone) } fn setup_env_for_git_repo() -> GitInfo { @@ -526,7 +526,7 @@ fn get_base_directory_name() -> Option { } } -fn setup_env_for_project(config: &Config, crate_info: &CrateInfo) { +fn setup_env_for_project(config: &Config, crate_info: &CrateInfo) -> Result<(), CargoMakeError> { let project_name = match crate_info.package { Some(ref package) => match package.name { Some(ref name) => Some(name.to_string()), @@ -554,7 +554,7 @@ fn setup_env_for_project(config: &Config, crate_info: &CrateInfo) { let mut path = PathBuf::new(); path.push(member); path.push("Cargo.toml"); - let member_crate_info = crateinfo::load_from(path); + let member_crate_info = crateinfo::load_from(path)?; match member_crate_info.package { Some(package) => package.version, @@ -571,6 +571,8 @@ fn setup_env_for_project(config: &Config, crate_info: &CrateInfo) { }; envmnt::set_or_remove("CARGO_MAKE_PROJECT_VERSION", &project_version); + + Ok(()) } /// Sets up the env before the tasks execution. @@ -602,7 +604,7 @@ pub(crate) fn setup_env( let crate_info = if config.config.skip_crate_env_info.unwrap_or(false) { CrateInfo::new() } else { - setup_env_for_crate(home.clone()) + setup_env_for_crate(home.clone())? }; time_summary::add(time_summary_vec, "[Setup Env - Crate Info]", now); @@ -631,7 +633,7 @@ pub(crate) fn setup_env( // setup project info now = SystemTime::now(); - setup_env_for_project(config, &crate_info); + setup_env_for_project(config, &crate_info)?; time_summary::add(time_summary_vec, "[Setup Env - Project]", now); // load env vars diff --git a/src/lib/environment/mod_test.rs b/src/lib/environment/mod_test.rs index 89e791ad..b180f916 100755 --- a/src/lib/environment/mod_test.rs +++ b/src/lib/environment/mod_test.rs @@ -1376,7 +1376,7 @@ fn setup_env_for_crate_load_toml_found() { envmnt::set("CARGO_MAKE_CRATE_HAS_DEPENDENCIES", "EMPTY"); envmnt::set("CARGO_MAKE_CRATE_WORKSPACE_MEMBERS", "EMPTY"); - setup_env_for_crate(None); + setup_env_for_crate(None).unwrap(); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_CRATE_NAME"), "cargo-make"); assert_eq!( @@ -1440,7 +1440,7 @@ fn setup_env_for_crate_load_toml_not_found_and_cwd() { assert!(envmnt::get_or_panic("CARGO_MAKE_WORKING_DIRECTORY") == "EMPTY"); setup_cwd(Some("examples")); - setup_env_for_crate(None); + setup_env_for_crate(None).unwrap(); setup_cwd(Some("..")); assert!(envmnt::get_or_panic("CARGO_MAKE_WORKING_DIRECTORY") != "EMPTY"); @@ -1472,7 +1472,7 @@ fn setup_env_for_crate_load_toml_not_found_and_cwd() { "" ); - setup_env_for_crate(None); + setup_env_for_crate(None).unwrap(); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_CRATE_NAME"), "cargo-make"); assert_eq!( @@ -1533,7 +1533,7 @@ fn setup_env_for_crate_workspace() { envmnt::set("CARGO_MAKE_CRATE_WORKSPACE_MEMBERS", "EMPTY"); setup_cwd(Some("examples/workspace")); - setup_env_for_crate(None); + setup_env_for_crate(None).unwrap(); setup_cwd(Some("../..")); assert_eq!(envmnt::get_or_panic("CARGO_MAKE_CRATE_NAME"), "EMPTY"); @@ -1900,12 +1900,12 @@ fn setup_env_for_project_crate() { plugins: None, }; - let crate_info = crateinfo::load(); + let crate_info = crateinfo::load().unwrap(); envmnt::remove("CARGO_MAKE_PROJECT_NAME"); envmnt::remove("CARGO_MAKE_PROJECT_VERSION"); - setup_env_for_project(&config, &crate_info); + setup_env_for_project(&config, &crate_info).unwrap(); assert!(envmnt::is_equal("CARGO_MAKE_PROJECT_NAME", "cargo-make")); assert!(envmnt::is_equal( @@ -1933,8 +1933,8 @@ fn setup_env_for_project_workspace_with_main_crate() { envmnt::remove("CARGO_MAKE_PROJECT_VERSION"); setup_cwd(Some("src/lib/test/workspace1")); - let crate_info = crateinfo::load(); - setup_env_for_project(&config, &crate_info); + let crate_info = crateinfo::load().unwrap(); + setup_env_for_project(&config, &crate_info).unwrap(); setup_cwd(Some("../../../..")); assert!(envmnt::is_equal("CARGO_MAKE_PROJECT_NAME", "workspace1")); @@ -1957,8 +1957,8 @@ fn setup_env_for_project_workspace_no_main_crate() { envmnt::remove("CARGO_MAKE_PROJECT_VERSION"); setup_cwd(Some("src/lib/test/workspace1")); - let crate_info = crateinfo::load(); - setup_env_for_project(&config, &crate_info); + let crate_info = crateinfo::load().unwrap(); + setup_env_for_project(&config, &crate_info).unwrap(); setup_cwd(Some("../../../..")); assert!(envmnt::is_equal("CARGO_MAKE_PROJECT_NAME", "workspace1")); diff --git a/src/lib/error.rs b/src/lib/error.rs index 5d0ada29..514183ef 100644 --- a/src/lib/error.rs +++ b/src/lib/error.rs @@ -28,7 +28,22 @@ pub enum CargoMakeError { #[strum(to_string = "Error while executing command, exit code: {0}")] ExitCodeError(i32) = 104, - #[strum(to_string = "Unable to run, minimum required version is: {0}")] + #[strum(to_string = "Unable to parse internal descriptor: {0}")] + DescriptorParseFailed(String) = 105, + + #[strum(to_string = "Unable to parse external file: {0:#?}, {1}")] + ParseFileFailed(String, String) = 106, + + #[strum(to_string = "{0}")] + Arity(&'static str) = 107, + + #[strum(to_string = "{0}")] + MethodCallRestriction(&'static str) = 108, + + #[strum(to_string = "Task {0:#?} is {1}")] + TaskIs(String, &'static str), + + #[strum(to_string = "{0}")] NotFound(String) = 404, // ************************ @@ -37,6 +52,9 @@ pub enum CargoMakeError { #[strum(to_string = "`std::io::Error` error. {error:?}")] StdIoError { error: std::io::Error } = 700, + #[strum(to_string = "`std::fmt::Error` error. {error:?}")] + StdFmtError { error: std::fmt::Error } = 709, + #[strum(to_string = "{0:?}")] ExitCode(std::process::ExitCode) = 710, @@ -64,6 +82,12 @@ impl From for CargoMakeError { } } +impl From for CargoMakeError { + fn from(error: std::fmt::Error) -> Self { + Self::StdFmtError { error } + } +} + impl From for CargoMakeError { fn from(error: toml::de::Error) -> Self { Self::TomlDeError { error } diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 72a3bd97..7241574a 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -312,12 +312,21 @@ fn is_workspace_flow( ) -> Result { // determine if workspace flow is explicitly set and enabled in the requested task let (task_set_workspace, task_enable_workspace) = - match get_optional_normalized_task(config, task, true)? { - Some(normalized_task) => match normalized_task.workspace { - Some(enable_workspace) => (true, enable_workspace), + match get_optional_normalized_task(config, task, true) { + Ok(optional_task) => match optional_task { + Some(normalized_task) => match normalized_task.workspace { + Some(enable_workspace) => (true, enable_workspace), + None => (false, false), + }, None => (false, false), }, - None => (false, false), + Err(e) => { + if let CargoMakeError::NotFound(_) = e { + (false, false) + } else { + return Err(e); + } + } }; // if project is not a workspace or if workspace is disabled via cli, return no workspace flow @@ -428,7 +437,7 @@ fn create_for_step( } } else { error!("Task {} is private", &task); - panic!("Task {} is private", &task); + return Err(CargoMakeError::TaskIs(format!("{}", &task), "private")); } Ok(()) } diff --git a/src/lib/execution_plan_test.rs b/src/lib/execution_plan_test.rs index f1a2267f..1dfb129b 100644 --- a/src/lib/execution_plan_test.rs +++ b/src/lib/execution_plan_test.rs @@ -1421,7 +1421,7 @@ fn create_workspace() { config.tasks.insert("test".to_string(), task); env::set_current_dir("./examples/workspace").unwrap(); - let crateinfo = environment::crateinfo::load(); + let crateinfo = environment::crateinfo::load().unwrap(); let execution_plan = create(&config, "test", &crateinfo, false, true, false, &None).unwrap(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); @@ -1445,7 +1445,7 @@ fn create_noworkspace() { config.tasks.insert("test".to_string(), task); env::set_current_dir("./examples/workspace").unwrap(); - let crateinfo = environment::crateinfo::load(); + let crateinfo = environment::crateinfo::load().unwrap(); let execution_plan = create(&config, "test", &crateinfo, true, true, false, &None).unwrap(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); diff --git a/src/lib/functions/mod.rs b/src/lib/functions/mod.rs index 8f23cadb..1e4ef212 100644 --- a/src/lib/functions/mod.rs +++ b/src/lib/functions/mod.rs @@ -13,23 +13,30 @@ mod remove_empty_func; mod split_func; mod trim_func; +use crate::error::CargoMakeError; use crate::types::{Step, Task}; -fn run_function(function_name: &str, function_args: &Vec) -> Vec { +fn run_function( + function_name: &str, + function_args: &Vec, +) -> Result, CargoMakeError> { debug!( "Running function: {} arguments: {:#?}", &function_name, &function_args ); match function_name { - "split" => split_func::invoke(function_args), - "remove-empty" => remove_empty_func::invoke(function_args), + "split" => Ok(split_func::invoke(function_args)), + "remove-empty" => Ok(remove_empty_func::invoke(function_args)), "trim" => trim_func::invoke(function_args), - "getat" => getat_func::invoke(function_args), - "decode" => decode_func::invoke(function_args), + "getat" => Ok(getat_func::invoke(function_args)), + "decode" => Ok(decode_func::invoke(function_args)), _ => { error!("Unknown function: {}", &function_name); - panic!("Unknown function: {}", &function_name); + Err(CargoMakeError::NotFound(format!( + "Unknown function: {}", + &function_name + ))) } } } @@ -70,7 +77,7 @@ fn get_function_arguments(function_string: &str) -> Option> { } } -fn evaluate_and_run(value: &str) -> Vec { +fn evaluate_and_run(value: &str) -> Result, CargoMakeError> { let value_string = value.to_string(); if value_string.starts_with("@@") { @@ -84,23 +91,23 @@ fn evaluate_and_run(value: &str) -> Vec { match func_args_option { Some(function_args) => run_function(&function_name, &function_args), - None => vec![value_string], + None => Ok(vec![value_string]), } } - None => vec![value_string], + None => Ok(vec![value_string]), } } else { - vec![value_string] + Ok(vec![value_string]) } } -fn modify_arguments(task: &mut Task) { +fn modify_arguments(task: &mut Task) -> Result<(), CargoMakeError> { task.args = match task.args { Some(ref args) => { let mut new_args = vec![]; for index in 0..args.len() { - let result_args = evaluate_and_run(&args[index]); + let result_args = evaluate_and_run(&args[index])?; for result_index in 0..result_args.len() { new_args.push(result_args[result_index].clone()); @@ -111,17 +118,18 @@ fn modify_arguments(task: &mut Task) { } None => None, }; + Ok(()) } -pub(crate) fn run(step: &Step) -> Step { +pub(crate) fn run(step: &Step) -> Result { //clone data before modify let mut config = step.config.clone(); //update args by running any needed function - modify_arguments(&mut config); + modify_arguments(&mut config)?; - Step { + Ok(Step { name: step.name.clone(), config, - } + }) } diff --git a/src/lib/functions/mod_test.rs b/src/lib/functions/mod_test.rs index bfb6e657..3c8957c0 100644 --- a/src/lib/functions/mod_test.rs +++ b/src/lib/functions/mod_test.rs @@ -3,13 +3,13 @@ use super::*; #[test] #[should_panic] fn run_function_empty() { - run_function("", &vec![]); + run_function("", &vec![]).unwrap(); } #[test] #[should_panic] fn run_function_not_exists() { - run_function("bad", &vec![]); + run_function("bad", &vec![]).unwrap(); } #[test] @@ -19,7 +19,8 @@ fn run_function_split() { let output = run_function( "split", &vec!["TEST_MOD_SPLIT_FUNC_MOD".to_string(), ",".to_string()], - ); + ) + .unwrap(); assert_eq!(output, vec!["1", "2", "3", "4"]); } @@ -35,7 +36,8 @@ fn run_function_getat() { ",".to_string(), "2".to_string(), ], - ); + ) + .unwrap(); assert_eq!(output, vec!["3"]); } @@ -47,7 +49,8 @@ fn run_function_remove_empty() { let output = run_function( "remove-empty", &vec!["TEST_MOD_REMOVE_EMPTY_FUNC_MOD".to_string()], - ); + ) + .unwrap(); assert_eq!(output.len(), 0); } @@ -56,7 +59,7 @@ fn run_function_remove_empty() { fn run_function_trim() { envmnt::set("TEST_MOD_TRIM_FUNC_MOD", " "); - let output = run_function("trim", &vec!["TEST_MOD_TRIM_FUNC_MOD".to_string()]); + let output = run_function("trim", &vec!["TEST_MOD_TRIM_FUNC_MOD".to_string()]).unwrap(); assert_eq!(output.len(), 0); } @@ -74,7 +77,8 @@ fn run_function_decode() { "ci".to_string(), "test".to_string(), ], - ); + ) + .unwrap(); assert_eq!(output, vec!["test"]); } @@ -168,7 +172,7 @@ fn get_function_arguments_multiple_with_spaces() { fn evaluate_and_run_valid() { envmnt::set("TEST_MOD_RUN_FUNC_VALUE", "1 2 3 4"); - let output = evaluate_and_run("@@split(TEST_MOD_RUN_FUNC_VALUE, )"); + let output = evaluate_and_run("@@split(TEST_MOD_RUN_FUNC_VALUE, )").unwrap(); assert_eq!(output, vec!["1", "2", "3", "4"]); } @@ -176,12 +180,12 @@ fn evaluate_and_run_valid() { #[test] #[should_panic] fn evaluate_and_run_unknown_function() { - evaluate_and_run("@@bad()"); + evaluate_and_run("@@bad()").unwrap(); } #[test] fn evaluate_and_run_no_function() { - let output = evaluate_and_run("value"); + let output = evaluate_and_run("value").unwrap(); assert_eq!(output, vec!["value"]); } @@ -197,7 +201,7 @@ fn modify_arguments_with_functions() { "end".to_string(), ]); - modify_arguments(&mut task); + modify_arguments(&mut task).unwrap(); assert_eq!(task.args.unwrap(), vec!["start", "1", "2", "3", "4", "end"]); } @@ -217,7 +221,7 @@ fn run_with_functions() { config: task, }; - step = run(&step); + step = run(&step).unwrap(); assert_eq!( step.config.args.unwrap(), diff --git a/src/lib/functions/trim_func.rs b/src/lib/functions/trim_func.rs index d5d06f8b..cb214d9d 100644 --- a/src/lib/functions/trim_func.rs +++ b/src/lib/functions/trim_func.rs @@ -4,13 +4,15 @@ //! The value will be removed if empty. //! +use crate::error::CargoMakeError; + #[cfg(test)] #[path = "trim_func_test.rs"] mod trim_func_test; -pub(crate) fn invoke(function_args: &Vec) -> Vec { +pub(crate) fn invoke(function_args: &Vec) -> Result, CargoMakeError> { if function_args.len() > 2 { - error!("trim expects up to 2 arguments (environment variable name and optionally start/end trim flag)"); + return Err(CargoMakeError::Arity("trim expects up to 2 arguments (environment variable name and optionally start/end trim flag)")); } let env_key = function_args[0].clone(); @@ -27,14 +29,16 @@ pub(crate) fn invoke(function_args: &Vec) -> Vec { "end" => value.trim_end().to_string(), _ => { error!("Invalid trim type provided, only start or end are supported."); - panic!("Invalid trim type provided, only start or end are supported."); + return Err(CargoMakeError::MethodCallRestriction( + "Invalid trim type provided, only start or end are supported.", + )); } } }; if trimmed_value.len() > 0 { - vec![trimmed_value] + Ok(vec![trimmed_value]) } else { - vec![] + Ok(vec![]) } } diff --git a/src/lib/functions/trim_func_test.rs b/src/lib/functions/trim_func_test.rs index d81f8f3a..7c8f4e13 100644 --- a/src/lib/functions/trim_func_test.rs +++ b/src/lib/functions/trim_func_test.rs @@ -3,26 +3,26 @@ use super::*; #[test] #[should_panic] fn trim_invoke_empty() { - invoke(&vec![]); + invoke(&vec![]).unwrap(); } #[test] #[should_panic] fn trim_invoke_invalid_too_many_args() { - invoke(&vec!["TEST".to_string(), "1".to_string(), "2".to_string()]); + invoke(&vec!["TEST".to_string(), "1".to_string(), "2".to_string()]).unwrap(); } #[test] #[should_panic] fn trim_invoke_invalid_trim_type() { - invoke(&vec!["TEST".to_string(), "bad".to_string()]); + invoke(&vec!["TEST".to_string(), "bad".to_string()]).unwrap(); } #[test] fn trim_invoke_exists_with_value() { envmnt::set("TEST_TRIM_VALID", "abc"); - let output = invoke(&vec!["TEST_TRIM_VALID".to_string()]); + let output = invoke(&vec!["TEST_TRIM_VALID".to_string()]).unwrap(); assert_eq!(output, vec!["abc"]); } @@ -31,14 +31,14 @@ fn trim_invoke_exists_with_value() { fn trim_invoke_exists_empty() { envmnt::set("TEST_TRIM_EMPTY", ""); - let output = invoke(&vec!["TEST_TRIM_EMPTY".to_string()]); + let output = invoke(&vec!["TEST_TRIM_EMPTY".to_string()]).unwrap(); assert_eq!(output.len(), 0); } #[test] fn trim_invoke_not_exists() { - let output = invoke(&vec!["TEST_TRIM_NOT_EXISTS".to_string()]); + let output = invoke(&vec!["TEST_TRIM_NOT_EXISTS".to_string()]).unwrap(); assert_eq!(output.len(), 0); } @@ -47,7 +47,7 @@ fn trim_invoke_not_exists() { fn trim_invoke_all_spaces() { envmnt::set("TEST_TRIM_ALL_SPACES", ""); - let output = invoke(&vec!["TEST_TRIM_ALL_SPACES".to_string()]); + let output = invoke(&vec!["TEST_TRIM_ALL_SPACES".to_string()]).unwrap(); assert_eq!(output.len(), 0); } @@ -56,7 +56,7 @@ fn trim_invoke_all_spaces() { fn trim_invoke_partial_spaces() { envmnt::set("TEST_TRIM_PARTIAL_SPACES", " 123 123 "); - let output = invoke(&vec!["TEST_TRIM_PARTIAL_SPACES".to_string()]); + let output = invoke(&vec!["TEST_TRIM_PARTIAL_SPACES".to_string()]).unwrap(); assert_eq!(output, vec!["123 123"]); } @@ -65,7 +65,7 @@ fn trim_invoke_partial_spaces() { fn trim_invoke_trim_start() { envmnt::set("TEST_TRIM_START", " 123 "); - let output = invoke(&vec!["TEST_TRIM_START".to_string(), "start".to_string()]); + let output = invoke(&vec!["TEST_TRIM_START".to_string(), "start".to_string()]).unwrap(); assert_eq!(output, vec!["123 "]); } @@ -74,7 +74,7 @@ fn trim_invoke_trim_start() { fn trim_invoke_trim_end() { envmnt::set("TEST_TRIM_END", " 123 "); - let output = invoke(&vec!["TEST_TRIM_END".to_string(), "end".to_string()]); + let output = invoke(&vec!["TEST_TRIM_END".to_string(), "end".to_string()]).unwrap(); assert_eq!(output, vec![" 123"]); } diff --git a/src/lib/installer/mod.rs b/src/lib/installer/mod.rs index 19368cec..2f5806f0 100644 --- a/src/lib/installer/mod.rs +++ b/src/lib/installer/mod.rs @@ -116,7 +116,9 @@ pub(crate) fn install( Some(ref crate_name) => (arg, crate_name.to_string()), None => { error!("Missing crate name to invoke."); - panic!("Missing crate name to invoke."); + return Err(CargoMakeError::NotFound(String::from( + "Missing crate name to invoke.", + ))); } }, None => match install_info.crate_name { @@ -125,7 +127,9 @@ pub(crate) fn install( } None => { error!("Missing cargo command to invoke."); - panic!("Missing crate command to invoke."); + return Err(CargoMakeError::NotFound(String::from( + "Missing crate command to invoke.", + ))); } }, }, diff --git a/src/lib/io.rs b/src/lib/io.rs index d36e7e13..2f6e5be2 100644 --- a/src/lib/io.rs +++ b/src/lib/io.rs @@ -7,6 +7,7 @@ #[path = "io_test.rs"] mod io_test; +use crate::error::CargoMakeError; use fsio::file::modify_file; use fsio::path as fsio_path; use fsio::path::from_path::FromPath; @@ -17,14 +18,14 @@ use std::fs::File; use std::io; use std::path::PathBuf; -pub(crate) fn create_text_file(text: &str, extension: &str) -> String { +pub(crate) fn create_text_file(text: &str, extension: &str) -> Result { let file_path = fsio_path::get_temporary_file_path(extension); match fsio::file::write_text_file(&file_path, text) { - Ok(_) => file_path, + Ok(_) => Ok(file_path), Err(error) => { error!("Unable to create file: {} {:#?}", &file_path, &error); - panic!("Unable to create file, error: {}", error); + Err(error.into()) } } } @@ -32,14 +33,14 @@ pub(crate) fn create_text_file(text: &str, extension: &str) -> String { pub(crate) fn create_file( write_content: &dyn Fn(&mut File) -> io::Result<()>, extension: &str, -) -> String { +) -> Result { let file_path = fsio_path::get_temporary_file_path(extension); match modify_file(&file_path, write_content, false) { - Ok(_) => file_path, + Ok(_) => Ok(file_path), Err(error) => { error!("Unable to write to file: {} {:#?}", &file_path, &error); - panic!("Unable to write to file, error: {}", error); + Err(error.into()) } } } @@ -58,13 +59,10 @@ pub(crate) fn write_text_file(file_path: &str, text: &str) -> bool { } } -pub(crate) fn read_text_file(file_path: &PathBuf) -> String { +pub(crate) fn read_text_file(file_path: &PathBuf) -> Result { debug!("Opening file: {:#?}", &file_path); - match fsio::file::read_text_file(file_path) { - Ok(content) => content, - Err(error) => panic!("Unable to read file: {:?} error: {:#?}", file_path, error), - } + Ok(fsio::file::read_text_file(file_path)?) } pub(crate) fn get_path_list( diff --git a/src/lib/io_test.rs b/src/lib/io_test.rs index c5b6352f..b422a36b 100644 --- a/src/lib/io_test.rs +++ b/src/lib/io_test.rs @@ -2,14 +2,14 @@ use super::*; #[test] fn create_text_file_read_and_delete() { - let file = create_text_file("test\nend", ".testfile"); + let file = create_text_file("test\nend", ".testfile").unwrap(); assert!(file.ends_with(".testfile")); let text = fsio::file::read_text_file(&file).unwrap(); let mut file_path = PathBuf::new(); file_path.push(&file); - let read_text = read_text_file(&file_path); + let read_text = read_text_file(&file_path).unwrap(); delete_file(&file); @@ -27,7 +27,7 @@ fn write_text_file_read_and_delete() { let mut file_path = PathBuf::new(); file_path.push(&file); - let read_text = read_text_file(&file_path); + let read_text = read_text_file(&file_path).unwrap(); delete_file(&file); diff --git a/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs b/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs index d75bc405..eefe775e 100644 --- a/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs +++ b/src/lib/plugin/sdk/cm_plugin_force_plugin_set_test.rs @@ -58,7 +58,7 @@ set_env FORCE_PLUGIN_SET_AND_CLEAR_FLOW_TEST_SET_4 1 ''' "#; - let config = descriptor_deserializer::load_config(&makefile_string, false); + let config = descriptor_deserializer::load_config(&makefile_string, false).unwrap(); let flow_info = FlowInfo { config, diff --git a/src/lib/runner.rs b/src/lib/runner.rs index 807bc429..d4c214b4 100755 --- a/src/lib/runner.rs +++ b/src/lib/runner.rs @@ -411,7 +411,7 @@ pub(crate) fn run_task_with_options( profile::set(&profile_name); // modify step using env and functions - let mut updated_step = functions::run(&step); + let mut updated_step = functions::run(&step)?; updated_step = environment::expand_env(&updated_step); let watch = should_watch(&step.config); diff --git a/src/lib/scriptengine/generic_script.rs b/src/lib/scriptengine/generic_script.rs index 588a5074..ffc9b5e4 100644 --- a/src/lib/scriptengine/generic_script.rs +++ b/src/lib/scriptengine/generic_script.rs @@ -41,7 +41,7 @@ pub(crate) fn execute( cli_arguments: &Vec, validate: bool, ) -> Result { - let file = create_script_file(script_text, &extension); + let file = create_script_file(script_text, &extension)?; let valid = run_file(&file, &runner, arguments, &mut cli_arguments.clone())?; diff --git a/src/lib/scriptengine/mod.rs b/src/lib/scriptengine/mod.rs index 78c85229..f1f9797f 100755 --- a/src/lib/scriptengine/mod.rs +++ b/src/lib/scriptengine/mod.rs @@ -43,10 +43,10 @@ pub(crate) enum EngineType { Unsupported, } -pub(crate) fn get_script_text(script: &ScriptValue) -> Vec { +pub(crate) fn get_script_text(script: &ScriptValue) -> Result, CargoMakeError> { match script { - ScriptValue::SingleLine(text) => vec![text.clone()], - ScriptValue::Text(text) => text.clone(), + ScriptValue::SingleLine(text) => Ok(vec![text.clone()]), + ScriptValue::Text(text) => Ok(text.clone()), ScriptValue::File(info) => { let mut file_path_string = String::new(); if !info.absolute_path.unwrap_or(false) { @@ -60,7 +60,7 @@ pub(crate) fn get_script_text(script: &ScriptValue) -> Vec { let mut file_path = PathBuf::new(); file_path.push(expanded_value); - let script_text = io::read_text_file(&file_path); + let script_text = io::read_text_file(&file_path)?; let lines: Vec<&str> = script_text.split('\n').collect(); let mut script_lines: Vec = vec![]; @@ -69,7 +69,7 @@ pub(crate) fn get_script_text(script: &ScriptValue) -> Vec { script_lines.push(line.to_string()); } - script_lines + Ok(script_lines) } ScriptValue::Sections(sections) => { let mut script_lines = vec![]; @@ -84,7 +84,7 @@ pub(crate) fn get_script_text(script: &ScriptValue) -> Vec { script_lines.push(text.to_string()); } - script_lines + Ok(script_lines) } } } @@ -108,7 +108,7 @@ pub(crate) fn get_engine_type( script: &ScriptValue, script_runner: &Option, script_extension: &Option, -) -> EngineType { +) -> Result { match script_runner { Some(ref runner) => { debug!("Checking script runner: {}", runner); @@ -120,19 +120,19 @@ pub(crate) fn get_engine_type( if script_extension.is_some() { // if both script runner and extension is defined, we use generic script runner debug!("Generic script detected."); - EngineType::Generic + Ok(EngineType::Generic) } else { // use default OS extension with custom runner debug!("OS script with custom runner detected."); - EngineType::OS + Ok(EngineType::OS) } } - _ => engine_type, + _ => Ok(engine_type), } } None => { // if no runner specified, try to extract it from script content - let script_text = get_script_text(&script); + let script_text = get_script_text(&script)?; let shebang = shebang_script::get_shebang(&script_text); match shebang.runner { @@ -143,15 +143,15 @@ pub(crate) fn get_engine_type( match engine_type { EngineType::Unsupported => { debug!("Shebang line does not point to an internal engine, using normal shebang script runner."); - EngineType::Shebang + Ok(EngineType::Shebang) } - _ => engine_type, + _ => Ok(engine_type), } } else { - EngineType::Shebang + Ok(EngineType::Shebang) } } - None => EngineType::OS, + None => Ok(EngineType::OS), } } } @@ -257,19 +257,19 @@ fn invoke_script( flow_state: Option>>, cli_arguments: &Vec, ) -> Result { - let engine_type = get_engine_type(script, &script_runner, &script_extension); + let engine_type = get_engine_type(script, &script_runner, &script_extension)?; match engine_type { EngineType::OS => { - let script_text = get_script_text(script); + let script_text = get_script_text(script)?; os_script::execute(&script_text, script_runner, cli_arguments, validate) } EngineType::Duckscript => { - let script_text = get_script_text(script); + let script_text = get_script_text(script)?; duck_script::execute(&script_text, cli_arguments, flow_info, flow_state, validate) } EngineType::Rust => { - let script_text = get_script_text(script); + let script_text = get_script_text(script)?; rsscript::execute( &script_text, script_runner_args.clone(), @@ -278,11 +278,11 @@ fn invoke_script( ) } EngineType::Shell2Batch => { - let script_text = get_script_text(script); + let script_text = get_script_text(script)?; shell_to_batch::execute(&script_text, cli_arguments, validate) } EngineType::Generic => { - let script_text = get_script_text(script); + let script_text = get_script_text(script)?; let extension = script_extension.clone().unwrap(); generic_script::execute( &script_text, @@ -294,7 +294,7 @@ fn invoke_script( ) } EngineType::Shebang => { - let script_text = get_script_text(script); + let script_text = get_script_text(script)?; let extension = script_extension.clone(); shebang_script::execute(&script_text, &extension, cli_arguments, validate) } diff --git a/src/lib/scriptengine/mod_test.rs b/src/lib/scriptengine/mod_test.rs index 7320243c..40d4692b 100755 --- a/src/lib/scriptengine/mod_test.rs +++ b/src/lib/scriptengine/mod_test.rs @@ -4,7 +4,9 @@ use crate::types::{FileScriptValue, ScriptSections}; #[test] fn get_script_text_single_line() { - let output = get_script_text(&ScriptValue::SingleLine("test".to_string())).join("\n"); + let output = get_script_text(&ScriptValue::SingleLine("test".to_string())) + .unwrap() + .join("\n"); assert_eq!(output, "test"); } @@ -15,6 +17,7 @@ fn get_script_text_vector() { "line 1".to_string(), "line 2".to_string(), ])) + .unwrap() .join("\n"); assert_eq!(output, "line 1\nline 2"); @@ -27,6 +30,7 @@ fn get_script_text_file() { absolute_path: None, }; let output = get_script_text(&ScriptValue::File(file_info)) + .unwrap() .join("\n") .replace("\r", ""); @@ -40,6 +44,7 @@ fn get_script_text_file_relative() { absolute_path: Some(false), }; let output = get_script_text(&ScriptValue::File(file_info)) + .unwrap() .join("\n") .replace("\r", ""); @@ -53,6 +58,7 @@ fn get_script_text_file_absolute() { absolute_path: Some(true), }; let output = get_script_text(&ScriptValue::File(file_info)) + .unwrap() .join("\n") .replace("\r", ""); @@ -66,6 +72,7 @@ fn get_script_text_script_content_sections() { main: Some("main".to_string()), post: Some("post".to_string()), })) + .unwrap() .join("\n"); assert_eq!(output, "pre\nmain\npost"); @@ -77,14 +84,16 @@ fn get_script_text_script_content_sections_empty() { pre: None, main: None, post: None, - })); + })) + .unwrap(); assert!(output.is_empty()); } #[test] fn get_engine_type_no_runner() { - let output = get_engine_type(&ScriptValue::Text(vec!["test".to_string()]), &None, &None); + let output = + get_engine_type(&ScriptValue::Text(vec!["test".to_string()]), &None, &None).unwrap(); assert_eq!(output, EngineType::OS); } @@ -95,7 +104,8 @@ fn get_engine_type_runner_no_extension() { &ScriptValue::Text(vec!["test".to_string()]), &Some("@bad".to_string()), &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::OS); } @@ -106,7 +116,8 @@ fn get_engine_type_duckscript() { &ScriptValue::Text(vec!["test".to_string()]), &Some("@duckscript".to_string()), &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::Duckscript); } @@ -117,7 +128,8 @@ fn get_engine_type_rust() { &ScriptValue::Text(vec!["test".to_string()]), &Some("@rust".to_string()), &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::Rust); } @@ -128,7 +140,8 @@ fn get_engine_type_shell_to_batch() { &ScriptValue::Text(vec!["test".to_string()]), &Some("@shell".to_string()), &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::Shell2Batch); } @@ -139,14 +152,16 @@ fn get_engine_type_generic() { &ScriptValue::Text(vec!["test".to_string()]), &Some("test1".to_string()), &Some("test2".to_string()), - ); + ) + .unwrap(); assert_eq!(output, EngineType::Generic); } #[test] fn get_engine_type_shebang() { - let output = get_engine_type(&ScriptValue::Text(vec!["#!bash".to_string()]), &None, &None); + let output = + get_engine_type(&ScriptValue::Text(vec!["#!bash".to_string()]), &None, &None).unwrap(); assert_eq!(output, EngineType::Shebang); } @@ -157,7 +172,8 @@ fn get_engine_type_duckscript_from_shebang() { &ScriptValue::Text(vec!["#!@duckscript".to_string()]), &None, &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::Duckscript); } @@ -168,7 +184,8 @@ fn get_engine_type_shell_to_batch_from_shebang() { &ScriptValue::Text(vec!["#!@shell".to_string()]), &None, &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::Shell2Batch); } @@ -179,7 +196,8 @@ fn get_engine_type_rust_from_shebang() { &ScriptValue::Text(vec!["#!@rust".to_string()]), &None, &None, - ); + ) + .unwrap(); assert_eq!(output, EngineType::Rust); } diff --git a/src/lib/scriptengine/rsscript.rs b/src/lib/scriptengine/rsscript.rs index 0ab2c4c6..25ff23eb 100755 --- a/src/lib/scriptengine/rsscript.rs +++ b/src/lib/scriptengine/rsscript.rs @@ -74,7 +74,7 @@ fn install_crate(provider: &ScriptRunner) -> Result<(), CargoMakeError> { Ok(()) } -fn create_rust_file(rust_script: &Vec) -> String { +fn create_rust_file(rust_script: &Vec) -> Result { create_persisted_script_file(rust_script, "rs") } @@ -121,7 +121,7 @@ pub(crate) fn execute( install_crate(&provider)?; - let file = create_rust_file(rust_script); + let file = create_rust_file(rust_script)?; let valid = run_file(&file, runner_arguments, &cli_arguments, &provider)?; diff --git a/src/lib/scriptengine/script_utils.rs b/src/lib/scriptengine/script_utils.rs index 66a5d8dc..2e1f3754 100644 --- a/src/lib/scriptengine/script_utils.rs +++ b/src/lib/scriptengine/script_utils.rs @@ -7,6 +7,7 @@ #[path = "script_utils_test.rs"] mod script_utils_test; +use crate::error::CargoMakeError; use crate::io::create_text_file; use fsio::file::write_text_file; use fsio::path::as_path::AsPath; @@ -14,18 +15,24 @@ use sha2::{Digest, Sha256}; use std::fmt::Write; use std::path::PathBuf; -pub(crate) fn create_script_file(script_text: &Vec, extension: &str) -> String { +pub(crate) fn create_script_file( + script_text: &Vec, + extension: &str, +) -> Result { let text = script_text.join("\n"); create_text_file(&text, &extension) } -pub(crate) fn create_persisted_script_file(script_text: &Vec, extension: &str) -> String { +pub(crate) fn create_persisted_script_file( + script_text: &Vec, + extension: &str, +) -> Result { let text = script_text.join("\n"); let string_bytes = text.as_bytes(); let bytes = Sha256::digest(string_bytes); - let file_name = bytes_to_hex(&bytes[..]); + let file_name = bytes_to_hex(&bytes[..])?; let default_target_directory = envmnt::get_or("CARGO_MAKE_CRATE_TARGET_DIRECTORY", "target"); let directory = envmnt::get_or( @@ -43,35 +50,23 @@ pub(crate) fn create_persisted_script_file(script_text: &Vec, extension: let file_path = file_path_string.as_path(); if file_path.exists() { - file_path_string + Ok(file_path_string) } else { match write_text_file(&file_path_string, &text) { - Ok(_) => file_path_string, + Ok(_) => Ok(file_path_string), Err(error) => { error!("Unable to create file: {} {:#?}", &file_path_string, &error); - panic!("Unable to create file, error: {}", error); + Err(error.into()) } } } } -fn bytes_to_hex(bytes: &[u8]) -> String { +fn bytes_to_hex(bytes: &[u8]) -> Result { let mut hex_string = String::with_capacity(2 * bytes.len()); for byte in bytes { - match write!(hex_string, "{:02X}", byte) { - Err(error) => { - error!( - "Unable to convert script hash to hex string, error: {}", - &error - ); - panic!( - "Unable to convert script hash to hex string, error: {}", - &error - ); - } - _ => (), - } + write!(hex_string, "{:02X}", byte)?; } - hex_string + Ok(hex_string) } diff --git a/src/lib/scriptengine/script_utils_test.rs b/src/lib/scriptengine/script_utils_test.rs index f7f6ef80..c6b41174 100644 --- a/src/lib/scriptengine/script_utils_test.rs +++ b/src/lib/scriptengine/script_utils_test.rs @@ -3,7 +3,8 @@ use crate::io; #[test] fn create_script_file_text() { - let file = create_script_file(&vec!["test".to_string(), "end".to_string()], ".testfile"); + let file = + create_script_file(&vec!["test".to_string(), "end".to_string()], ".testfile").unwrap(); assert!(file.ends_with(".testfile")); let text = fsio::file::read_text_file(&file).unwrap(); @@ -16,20 +17,23 @@ fn create_script_file_text() { #[test] fn create_persisted_script_file_text() { let mut file = - create_persisted_script_file(&vec!["test".to_string(), "end".to_string()], ".testfile"); + create_persisted_script_file(&vec!["test".to_string(), "end".to_string()], ".testfile") + .unwrap(); assert!(file.ends_with(".testfile")); let mut text = fsio::file::read_text_file(&file).unwrap(); io::delete_file(&file); assert_eq!("test\nend".to_string(), text); let file1 = - create_persisted_script_file(&vec!["test".to_string(), "end".to_string()], ".testfile"); + create_persisted_script_file(&vec!["test".to_string(), "end".to_string()], ".testfile") + .unwrap(); assert_eq!(file, file1); text = fsio::file::read_text_file(&file).unwrap(); assert_eq!("test\nend".to_string(), text); io::delete_file(&file); - file = create_persisted_script_file(&vec!["test2".to_string(), "end".to_string()], ".testfile"); + file = create_persisted_script_file(&vec!["test2".to_string(), "end".to_string()], ".testfile") + .unwrap(); assert_ne!(file, file1); text = fsio::file::read_text_file(&file).unwrap(); assert_eq!("test2\nend".to_string(), text); From d085444f5a72e15af204586d58730d0b8b3554f2 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:55:44 -0400 Subject: [PATCH 10/21] [src/lib/cli_test.rs] Fix `run_valid` ; [{src/lib/types.rs,Cargo{.toml,.lock}] Remove `either` --- Cargo.lock | 1 - Cargo.toml | 1 - src/lib/cli_test.rs | 11 +++-------- src/lib/types.rs | 15 --------------- 4 files changed, 3 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c319f6ca..40fe66ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,7 +150,6 @@ dependencies = [ "dirs-next", "duckscript", "duckscriptsdk", - "either", "envmnt", "expect-test", "fern", diff --git a/Cargo.toml b/Cargo.toml index e6f1b10d..2addd838 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ ctrlc = "^3" dirs-next = "^2" duckscript = "^0.8.0" duckscriptsdk = { version = "^0.9.3", default-features = false } -either = "1.13.0" envmnt = "^0.10.4" fern = "^0.6" fsio = { version = "^0.4", features = ["temp-path"] } diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index 18c3c4b7..e193cb41 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -430,15 +430,10 @@ fn run_valid() { "arg2", "arg3", ]), - ); + ) + .unwrap(); - assert_eq!( - format!( - "{:?}", - run(&cli_args.unwrap(), &global_config).err().unwrap() - ), - format!("{:?}", std::process::ExitCode::FAILURE) - ); + assert_eq!(run(&cli_args, &global_config).unwrap(), ()); } #[test] diff --git a/src/lib/types.rs b/src/lib/types.rs index ffa61a6e..4582c09e 100755 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -10,7 +10,6 @@ mod types_test; use crate::legacy; use crate::plugin::types::Plugins; use ci_info::types::CiInfo; -use either::Either; use git_info::types::GitInfo; use indexmap::{IndexMap, IndexSet}; use regex::Regex; @@ -2452,17 +2451,3 @@ pub struct CommandSpec { /// The command args pub args: Option>, } - -pub fn either_to_result(either: Either) -> Result { - match either { - Either::Left(lhs) => Ok(lhs), - Either::Right(rhs) => Err(rhs), - } -} - -pub fn result_to_either(result: Result) -> Either { - match result { - Ok(lhs) => Either::Left(lhs), - Err(rhs) => Either::Right(rhs), - } -} From 3639ec357094c057b63f4d3555d0bc6f383963e5 Mon Sep 17 00:00:00 2001 From: Kaiyi Li Date: Sun, 7 Jul 2024 11:31:45 -0700 Subject: [PATCH 11/21] Add ExecutionPlanBuilder ... to provide reasonable default values for creation parameters, and we don't have to modify many tests when we add another parameter for ExecutionPlan creation. --- src/lib/cli_commands/diff_steps.rs | 36 +++-- src/lib/cli_commands/print_steps.rs | 16 +-- src/lib/execution_plan.rs | 139 +++++++++++-------- src/lib/execution_plan_test.rs | 201 +++++++++++----------------- src/lib/runner.rs | 16 +-- 5 files changed, 196 insertions(+), 212 deletions(-) diff --git a/src/lib/cli_commands/diff_steps.rs b/src/lib/cli_commands/diff_steps.rs index 01991bc9..1ae02f9d 100644 --- a/src/lib/cli_commands/diff_steps.rs +++ b/src/lib/cli_commands/diff_steps.rs @@ -8,7 +8,7 @@ mod diff_steps_test; use crate::command; -use crate::execution_plan::create as create_execution_plan; +use crate::execution_plan::ExecutionPlanBuilder; use crate::io::{create_file, delete_file}; use crate::types::{CliArgs, Config, CrateInfo, ExecutionPlan}; use regex::Regex; @@ -40,25 +40,23 @@ pub(crate) fn run( None => None, }; - let internal_execution_plan = create_execution_plan( - internal_config, - &task, - crateinfo, - cli_args.disable_workspace, - true, - false, - &skip_tasks_pattern, - ); + let internal_execution_plan = ExecutionPlanBuilder { + crate_info: Some(crateinfo), + disable_workspace: cli_args.disable_workspace, + allow_private: true, + skip_tasks_pattern: skip_tasks_pattern.as_ref(), + ..ExecutionPlanBuilder::new(internal_config, &task) + } + .build(); - let external_execution_plan = create_execution_plan( - external_config, - &task, - crateinfo, - cli_args.disable_workspace, - true, - false, - &skip_tasks_pattern, - ); + let external_execution_plan = ExecutionPlanBuilder { + crate_info: Some(crateinfo), + disable_workspace: cli_args.disable_workspace, + allow_private: true, + skip_tasks_pattern: skip_tasks_pattern.as_ref(), + ..ExecutionPlanBuilder::new(external_config, &task) + } + .build(); let internal_file = create_file( &move |file: &mut File| write_as_string(&internal_execution_plan, &file), diff --git a/src/lib/cli_commands/print_steps.rs b/src/lib/cli_commands/print_steps.rs index cdc5a2ff..45bc4b7e 100644 --- a/src/lib/cli_commands/print_steps.rs +++ b/src/lib/cli_commands/print_steps.rs @@ -7,7 +7,7 @@ #[path = "print_steps_test.rs"] mod print_steps_test; -use crate::execution_plan::create as create_execution_plan; +use crate::execution_plan::ExecutionPlanBuilder; use crate::types::{Config, CrateInfo, ExecutionPlan}; use regex::Regex; @@ -80,15 +80,13 @@ pub(crate) fn print( None => None, }; - let execution_plan = create_execution_plan( - &config, - &task, - crateinfo, + let execution_plan = ExecutionPlanBuilder { + crate_info: Some(crateinfo), disable_workspace, - false, - false, - &skip_tasks_pattern_regex, - ); + skip_tasks_pattern: skip_tasks_pattern_regex.as_ref(), + ..ExecutionPlanBuilder::new(&config, &task) + } + .build(); debug!("Created execution plan: {:#?}", &execution_plan); let print_format = get_format_type(&output_format); diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 6c8ba795..24973878 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -336,7 +336,7 @@ fn create_for_step( task_names: &mut HashSet, root: bool, allow_private: bool, - skip_tasks_pattern: &Option, + skip_tasks_pattern: Option<&Regex>, ) { if let Some(skip_tasks_pattern_regex) = skip_tasks_pattern { if skip_tasks_pattern_regex.is_match(&task.name) { @@ -432,68 +432,95 @@ fn add_predefined_step(config: &Config, task: &str, steps: &mut Vec) { } } -/// Creates the full execution plan -pub(crate) fn create( - config: &Config, - task: &str, - crate_info: &CrateInfo, - disable_workspace: bool, - allow_private: bool, - sub_flow: bool, - skip_tasks_pattern: &Option, -) -> ExecutionPlan { - let mut task_names = HashSet::new(); - let mut steps = Vec::new(); - - if !sub_flow { - match config.config.legacy_migration_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), - None => debug!("Legacy migration task not defined."), - }; - match config.config.init_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), - None => debug!("Init task not defined."), - }; +#[derive(Clone, Debug)] +pub(crate) struct ExecutionPlanBuilder<'a> { + pub config: &'a Config, + pub task: &'a str, + pub crate_info: Option<&'a CrateInfo>, + pub disable_workspace: bool, + pub allow_private: bool, + pub sub_flow: bool, + pub skip_tasks_pattern: Option<&'a Regex>, +} + +impl<'a> ExecutionPlanBuilder<'a> { + pub fn new(config: &'a Config, task: &'a str) -> Self { + Self { + config, + task, + crate_info: None, + disable_workspace: false, + allow_private: false, + sub_flow: false, + skip_tasks_pattern: None, + } } - let skip = match skip_tasks_pattern { - Some(ref pattern) => pattern.is_match(task), - None => false, - }; + pub fn build(&self) -> ExecutionPlan { + let Self { + config, + task, + crate_info, + disable_workspace, + allow_private, + sub_flow, + skip_tasks_pattern, + } = *self; + let mut task_names = HashSet::new(); + let mut steps = Vec::new(); + let default_crate_info = CrateInfo::new(); + let crate_info = crate_info.unwrap_or(&default_crate_info); + + if !sub_flow { + match config.config.legacy_migration_task { + Some(ref task) => add_predefined_step(config, task, &mut steps), + None => debug!("Legacy migration task not defined."), + }; + match config.config.init_task { + Some(ref task) => add_predefined_step(config, task, &mut steps), + None => debug!("Init task not defined."), + }; + } + + let skip = match skip_tasks_pattern { + Some(pattern) => pattern.is_match(task), + None => false, + }; - if !skip { - let workspace_flow = - is_workspace_flow(&config, &task, disable_workspace, &crate_info, sub_flow); + if !skip { + let workspace_flow = + is_workspace_flow(&config, &task, disable_workspace, &crate_info, sub_flow); - if workspace_flow { - let workspace_task = create_workspace_task(crate_info, task); + if workspace_flow { + let workspace_task = create_workspace_task(crate_info, task); - steps.push(Step { - name: "workspace".to_string(), - config: workspace_task, - }); + steps.push(Step { + name: "workspace".to_string(), + config: workspace_task, + }); + } else { + create_for_step( + &config, + &TaskIdentifier::from_name(task), + &mut steps, + &mut task_names, + true, + allow_private, + skip_tasks_pattern, + ); + } } else { - create_for_step( - &config, - &TaskIdentifier::from_name(task), - &mut steps, - &mut task_names, - true, - allow_private, - &skip_tasks_pattern, - ); + debug!("Skipping task: {} due to skip pattern.", &task); } - } else { - debug!("Skipping task: {} due to skip pattern.", &task); - } - if !sub_flow { - // always add end task even if already executed due to some dependency - match config.config.end_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), - None => debug!("Ent task not defined."), - }; - } + if !sub_flow { + // always add end task even if already executed due to some dependency + match config.config.end_task { + Some(ref task) => add_predefined_step(config, task, &mut steps), + None => debug!("Ent task not defined."), + }; + } - ExecutionPlan { steps } + ExecutionPlan { steps } + } } diff --git a/src/lib/execution_plan_test.rs b/src/lib/execution_plan_test.rs index 4778fb99..7c22eda8 100644 --- a/src/lib/execution_plan_test.rs +++ b/src/lib/execution_plan_test.rs @@ -789,15 +789,11 @@ fn create_single() { config.tasks.insert("test".to_string(), task); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -826,15 +822,11 @@ fn create_single_disabled() { config.tasks.insert("test".to_string(), task); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "end"); @@ -863,15 +855,7 @@ fn create_single_private() { config.tasks.insert("test-private".to_string(), task); - create( - &config, - "test-private", - &CrateInfo::new(), - false, - false, - false, - &None, - ); + ExecutionPlanBuilder::new(&config, "test-private").build(); } #[test] @@ -896,15 +880,11 @@ fn create_single_allow_private() { config.tasks.insert("test-private".to_string(), task); - let execution_plan = create( - &config, - "test-private", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test-private") + } + .build(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test-private"); @@ -938,15 +918,11 @@ fn create_with_dependencies() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "task_dependency"); @@ -984,15 +960,11 @@ fn create_with_foreign_dependencies_directory() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1035,15 +1007,11 @@ fn create_with_foreign_dependencies_filename() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1086,15 +1054,11 @@ fn create_with_foreign_dependencies_file_and_directory() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1134,7 +1098,12 @@ fn create_with_dependencies_sub_flow() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create(&config, "test", &CrateInfo::new(), false, true, true, &None); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + sub_flow: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "task_dependency"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -1168,15 +1137,11 @@ fn create_disabled_task_with_dependencies() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "end"); @@ -1210,15 +1175,11 @@ fn create_with_dependencies_disabled() { .tasks .insert("task_dependency".to_string(), task_dependency); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -1327,15 +1288,11 @@ fn create_platform_disabled() { config.tasks.insert("test".to_string(), task); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 0); } @@ -1369,15 +1326,12 @@ fn create_with_dependencies_and_skip_filter() { let skip_filter = Regex::new("filtered.*").unwrap(); - let execution_plan = create( - &config, - "test", - &CrateInfo::new(), - false, - true, - false, - &Some(skip_filter), - ); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + skip_tasks_pattern: Some(&skip_filter), + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "task_dependency"); @@ -1403,7 +1357,12 @@ fn create_workspace() { env::set_current_dir("./examples/workspace").unwrap(); let crateinfo = environment::crateinfo::load(); - let execution_plan = create(&config, "test", &crateinfo, false, true, false, &None); + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + crate_info: Some(&crateinfo), + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "workspace"); @@ -1427,7 +1386,13 @@ fn create_noworkspace() { env::set_current_dir("./examples/workspace").unwrap(); let crateinfo = environment::crateinfo::load(); - let execution_plan = create(&config, "test", &crateinfo, true, true, false, &None); + let execution_plan = ExecutionPlanBuilder { + disable_workspace: true, + allow_private: true, + crate_info: Some(&crateinfo), + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "test"); @@ -1444,15 +1409,11 @@ fn create_task_extends_empty_env_bug_verification() { ) .unwrap(); - let execution_plan = create( - &config, - "task2", - &CrateInfo::new(), - true, - false, - false, - &None, - ); + let execution_plan = ExecutionPlanBuilder { + disable_workspace: true, + ..ExecutionPlanBuilder::new(&config, "task2") + } + .build(); assert_eq!(execution_plan.steps.len(), 3); diff --git a/src/lib/runner.rs b/src/lib/runner.rs index c774314a..8589fdcd 100755 --- a/src/lib/runner.rs +++ b/src/lib/runner.rs @@ -15,7 +15,7 @@ mod runner_test; use crate::command; use crate::condition; use crate::environment; -use crate::execution_plan::create as create_execution_plan; +use crate::execution_plan::ExecutionPlanBuilder; use crate::functions; use crate::installer; use crate::logger; @@ -563,15 +563,15 @@ fn create_watch_task(task: &str, options: Option, flow_info: & pub(crate) fn run_flow(flow_info: &FlowInfo, flow_state: Rc>, sub_flow: bool) { let allow_private = sub_flow || flow_info.allow_private; - let execution_plan = create_execution_plan( - &flow_info.config, - &flow_info.task, - &flow_info.env_info.crate_info, - flow_info.disable_workspace, + let execution_plan = ExecutionPlanBuilder { + crate_info: Some(&flow_info.env_info.crate_info), + disable_workspace: flow_info.disable_workspace, allow_private, sub_flow, - &flow_info.skip_tasks_pattern, - ); + skip_tasks_pattern: flow_info.skip_tasks_pattern.as_ref(), + ..ExecutionPlanBuilder::new(&flow_info.config, &flow_info.task) + } + .build(); debug!("Created execution plan: {:#?}", &execution_plan); run_task_flow(&flow_info, flow_state, &execution_plan); From 4dfc58529a1ccd40dd5ac9604b7fef8ac58f7906 Mon Sep 17 00:00:00 2001 From: Kaiyi Li Date: Sun, 7 Jul 2024 12:06:21 -0700 Subject: [PATCH 12/21] Fix --skip-init-end-tasks argument When we actually schedule the internal flow, we don't respect the --skip-init-end-tasks argument. --- CHANGELOG.md | 4 ++ src/lib/cli.rs | 8 ++- src/lib/cli_commands/print_steps.rs | 31 +++++++-- src/lib/cli_commands/print_steps_test.rs | 86 ++++++++++++++++++++++-- src/lib/execution_plan.rs | 8 ++- src/lib/execution_plan_test.rs | 31 +++++++++ src/lib/runner.rs | 1 + src/lib/runner_test.rs | 68 +++++++++++++++++++ 8 files changed, 221 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70d63c34..05646c9d 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## CHANGELOG +### v0.37.14 + +* Fix: fix the --skip-init-end-tasks argument #1108 + ### v0.37.13 (2024-07-07) * Enhancement: New condition_script_runner_args attribute #1081 diff --git a/src/lib/cli.rs b/src/lib/cli.rs index d0e74358..9c664851 100644 --- a/src/lib/cli.rs +++ b/src/lib/cli.rs @@ -149,14 +149,18 @@ fn run(cli_args: CliArgs, global_config: &GlobalConfig) { &env_info.crate_info, ); } else if cli_args.print_only { - cli_commands::print_steps::print( + if let Err(e) = cli_commands::print_steps::print( + &mut std::io::stdout(), &config, &task, &cli_args.output_format, cli_args.disable_workspace, cli_args.skip_tasks_pattern, &env_info.crate_info, - ); + cli_args.skip_init_end_tasks, + ) { + error!("Failed to print steps: {}", e); + } } else { runner::run( config, diff --git a/src/lib/cli_commands/print_steps.rs b/src/lib/cli_commands/print_steps.rs index 45bc4b7e..e2911942 100644 --- a/src/lib/cli_commands/print_steps.rs +++ b/src/lib/cli_commands/print_steps.rs @@ -7,6 +7,8 @@ #[path = "print_steps_test.rs"] mod print_steps_test; +use std::io; + use crate::execution_plan::ExecutionPlanBuilder; use crate::types::{Config, CrateInfo, ExecutionPlan}; use regex::Regex; @@ -42,7 +44,10 @@ fn get_format_type(output_format: &str) -> PrintFormat { } } -fn print_short_description(execution_plan: &ExecutionPlan) { +fn print_short_description( + output_buffer: &mut impl io::Write, + execution_plan: &ExecutionPlan, +) -> io::Result<()> { let mut counter = 1; for step in &execution_plan.steps { let task = &step.config; @@ -50,25 +55,35 @@ fn print_short_description(execution_plan: &ExecutionPlan) { Some(value) => value, None => "no description", }; - println!("{}. {} - {}", counter, &step.name, &description); + writeln!( + output_buffer, + "{}. {} - {}", + counter, &step.name, &description + )?; counter = counter + 1; } + Ok(()) } -fn print_default(execution_plan: &ExecutionPlan) { - println!("{:#?}", &execution_plan); +fn print_default( + output_buffer: &mut impl io::Write, + execution_plan: &ExecutionPlan, +) -> io::Result<()> { + writeln!(output_buffer, "{:#?}", &execution_plan) } /// Only prints the execution plan pub(crate) fn print( + output_buffer: &mut impl io::Write, config: &Config, task: &str, output_format: &str, disable_workspace: bool, skip_tasks_pattern: Option, crateinfo: &CrateInfo, -) { + skip_init_end_tasks: bool, +) -> io::Result<()> { let skip_tasks_pattern_regex = match skip_tasks_pattern { Some(ref pattern) => match Regex::new(pattern) { Ok(reg) => Some(reg), @@ -84,6 +99,7 @@ pub(crate) fn print( crate_info: Some(crateinfo), disable_workspace, skip_tasks_pattern: skip_tasks_pattern_regex.as_ref(), + skip_init_end_tasks, ..ExecutionPlanBuilder::new(&config, &task) } .build(); @@ -92,7 +108,8 @@ pub(crate) fn print( let print_format = get_format_type(&output_format); match print_format { - PrintFormat::ShortDescription => print_short_description(&execution_plan), - PrintFormat::Default => print_default(&execution_plan), + PrintFormat::ShortDescription => print_short_description(output_buffer, &execution_plan)?, + PrintFormat::Default => print_default(output_buffer, &execution_plan)?, }; + Ok(()) } diff --git a/src/lib/cli_commands/print_steps_test.rs b/src/lib/cli_commands/print_steps_test.rs index 7ec991f3..2d0ce0a4 100644 --- a/src/lib/cli_commands/print_steps_test.rs +++ b/src/lib/cli_commands/print_steps_test.rs @@ -35,7 +35,17 @@ fn print_default_format() { config.tasks.insert("end".to_string(), Task::new()); config.tasks.insert("test".to_string(), Task::new()); - print(&config, "test", "default", false, None, &CrateInfo::new()); + print( + &mut std::io::stdout(), + &config, + "test", + "default", + false, + None, + &CrateInfo::new(), + false, + ) + .expect("print should succeed"); } #[test] @@ -53,7 +63,17 @@ fn print_task_not_found() { config.tasks.insert("init".to_string(), Task::new()); config.tasks.insert("end".to_string(), Task::new()); - print(&config, "test", "default", false, None, &CrateInfo::new()); + print( + &mut std::io::stdout(), + &config, + "test", + "default", + false, + None, + &CrateInfo::new(), + false, + ) + .expect("print should succeed"); } #[test] @@ -71,13 +91,16 @@ fn print_task_not_found_but_skipped() { config.tasks.insert("end".to_string(), Task::new()); print( + &mut std::io::stdout(), &config, "test", "default", false, Some("test".to_string()), &CrateInfo::new(), - ); + false, + ) + .expect("print should succeed"); } #[test] @@ -89,7 +112,7 @@ fn print_default_valid() { let steps = vec![step]; let execution_plan = ExecutionPlan { steps }; - print_default(&execution_plan); + print_default(&mut std::io::stdout(), &execution_plan).expect("print should succeed"); } #[test] @@ -101,5 +124,58 @@ fn print_short_description_valid() { let steps = vec![step]; let execution_plan = ExecutionPlan { steps }; - print_short_description(&execution_plan); + print_short_description(&mut std::io::stdout(), &execution_plan).expect("print should succeed"); +} + +#[test] +fn print_skip_init_end_tasks() { + // Use a unique string, so that we are certain it shouldn't appear in the output. + let init_task_name = "init_5ec3_5b28_7b73_dcee"; + let end_task_name = "end_3afa_4ede_b49a_1767"; + + let tasks = IndexMap::from([ + (init_task_name.to_string(), Task::new()), + (end_task_name.to_string(), Task::new()), + ("entry".to_string(), Task::new()), + ]); + + // Test with only init_task enabled. + let config = Config { + config: ConfigSection { + init_task: Some(init_task_name.to_string()), + end_task: Some(end_task_name.to_string()), + ..ConfigSection::new() + }, + env_files: vec![], + env: IndexMap::new(), + env_scripts: vec![], + tasks, + plugins: None, + }; + + let mut output_bytes = Vec::::new(); + print( + &mut output_bytes, + &config, + "entry", + "default", + false, + None, + &CrateInfo::new(), + true, + ) + .expect("print should succeed"); + let output = std::str::from_utf8(&output_bytes).expect("output must be valid UTF-8 strings"); + assert!( + !output.contains(init_task_name), + "output {} shouldn't contain the init task name {}", + output, + init_task_name + ); + assert!( + !output.contains(end_task_name), + "output {} shouldn't contain the end task name {}", + output, + end_task_name + ); } diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 24973878..2bc58b0c 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -441,6 +441,7 @@ pub(crate) struct ExecutionPlanBuilder<'a> { pub allow_private: bool, pub sub_flow: bool, pub skip_tasks_pattern: Option<&'a Regex>, + pub skip_init_end_tasks: bool, } impl<'a> ExecutionPlanBuilder<'a> { @@ -453,6 +454,7 @@ impl<'a> ExecutionPlanBuilder<'a> { allow_private: false, sub_flow: false, skip_tasks_pattern: None, + skip_init_end_tasks: false, } } @@ -465,13 +467,15 @@ impl<'a> ExecutionPlanBuilder<'a> { allow_private, sub_flow, skip_tasks_pattern, + skip_init_end_tasks, } = *self; let mut task_names = HashSet::new(); let mut steps = Vec::new(); let default_crate_info = CrateInfo::new(); let crate_info = crate_info.unwrap_or(&default_crate_info); + let skip_init_end_tasks = skip_init_end_tasks || sub_flow; - if !sub_flow { + if !skip_init_end_tasks { match config.config.legacy_migration_task { Some(ref task) => add_predefined_step(config, task, &mut steps), None => debug!("Legacy migration task not defined."), @@ -513,7 +517,7 @@ impl<'a> ExecutionPlanBuilder<'a> { debug!("Skipping task: {} due to skip pattern.", &task); } - if !sub_flow { + if !skip_init_end_tasks { // always add end task even if already executed due to some dependency match config.config.end_task { Some(ref task) => add_predefined_step(config, task, &mut steps), diff --git a/src/lib/execution_plan_test.rs b/src/lib/execution_plan_test.rs index 7c22eda8..7b2c2a62 100644 --- a/src/lib/execution_plan_test.rs +++ b/src/lib/execution_plan_test.rs @@ -1584,3 +1584,34 @@ fn get_normalized_task_simple() { assert_eq!(task.command.unwrap(), "echo"); assert_eq!(task.args.unwrap(), vec!["1".to_string()]); } + +#[test] +fn respect_skip_init_end_tasks() { + let mut config_section = ConfigSection::new(); + config_section.init_task = Some("init".to_string()); + config_section.end_task = Some("end".to_string()); + let mut config = Config { + config: config_section, + env_files: vec![], + env: IndexMap::new(), + env_scripts: vec![], + tasks: IndexMap::new(), + plugins: None, + }; + + config.tasks.insert("init".to_string(), Task::new()); + config.tasks.insert("end".to_string(), Task::new()); + + let task = Task::new(); + + config.tasks.insert("test".to_string(), task); + + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + skip_init_end_tasks: true, + ..ExecutionPlanBuilder::new(&config, "test") + } + .build(); + assert_eq!(execution_plan.steps.len(), 1); + assert_eq!(execution_plan.steps[0].name, "test"); +} diff --git a/src/lib/runner.rs b/src/lib/runner.rs index 8589fdcd..aad2a0e0 100755 --- a/src/lib/runner.rs +++ b/src/lib/runner.rs @@ -569,6 +569,7 @@ pub(crate) fn run_flow(flow_info: &FlowInfo, flow_state: Rc>, allow_private, sub_flow, skip_tasks_pattern: flow_info.skip_tasks_pattern.as_ref(), + skip_init_end_tasks: flow_info.skip_init_end_tasks, ..ExecutionPlanBuilder::new(&flow_info.config, &flow_info.task) } .build(); diff --git a/src/lib/runner_test.rs b/src/lib/runner_test.rs index 4b645a82..13ffb2c5 100755 --- a/src/lib/runner_test.rs +++ b/src/lib/runner_test.rs @@ -2501,3 +2501,71 @@ fn create_fork_step_valid() { assert_eq!(args[8], makefile); assert_eq!(args[9], "test".to_string()); } + +#[test] +#[ignore] +fn run_flow_skip_init_end_tasks() { + // Init logger to panic at error. + crate::test::on_test_startup(); + + let fail_task = Task { + // Use duckscript, so that the behavior of the script is the same on all platforms. + script_runner: Some("@duckscript".to_string()), + script: Some(ScriptValue::Text(vec!["exit 1".to_string()])), + ..Task::new() + }; + + let entry_task = Task { + script_runner: Some("@duckscript".to_string()), + script: Some(ScriptValue::Text(vec!["echo test".to_string()])), + ..Task::new() + }; + + let tasks = IndexMap::from([ + ("fail".to_string(), fail_task), + ("entry".to_string(), entry_task), + ]); + + // Test with only init_task existing. + let config = Config { + config: ConfigSection { + init_task: Some("fail".to_string()), + ..ConfigSection::new() + }, + env_files: vec![], + env: IndexMap::new(), + env_scripts: vec![], + tasks, + plugins: None, + }; + let flow_info = FlowInfo { + config, + task: "entry".to_string(), + env_info: EnvInfo { + rust_info: RustInfo::new(), + crate_info: CrateInfo::new(), + git_info: GitInfo::new(), + ci_info: ci_info::get(), + }, + disable_workspace: false, + disable_on_error: false, + allow_private: false, + skip_init_end_tasks: true, + skip_tasks_pattern: None, + cli_arguments: None, + }; + + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + + // Test with only end_task existing. + let flow_info = { + let mut flow_info = flow_info; + flow_info.config.config = ConfigSection { + end_task: Some("fail".to_string()), + ..ConfigSection::new() + }; + flow_info + }; + + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); +} From cb11b71dae4d2767fef33a333840d411cf9a89b4 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sat, 13 Jul 2024 11:51:42 -0400 Subject: [PATCH 13/21] [src/lib/error.rs] Remove commented out code that only works in nightly with `#![feature(try_trait_v2)]` --- src/lib/error.rs | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/lib/error.rs b/src/lib/error.rs index 514183ef..f6b94c8e 100644 --- a/src/lib/error.rs +++ b/src/lib/error.rs @@ -165,30 +165,3 @@ impl std::process::Termination for SuccessOrCargoMakeError { } } } - -/* -// TODO: Get `Into` syntax working -impl std::ops::FromResidual> -for SuccessOrCargoMakeError -{ - fn from_residual(residual: Result) -> Self { - if let Err(e) = residual { - SuccessOrCargoMakeError::Err(e) - } else { - SuccessOrCargoMakeError::Ok(std::process::ExitCode::SUCCESS) - } - } -} - -impl std::ops::FromResidual> -for SuccessOrCargoMakeError -{ - fn from_residual(residual: Result) -> Self { - if let Err(e) = residual { - SuccessOrCargoMakeError::Err(e.into()) - } else { - SuccessOrCargoMakeError::Ok(std::process::ExitCode::SUCCESS) - } - } -} -*/ From 78e13aa9a65faf02291c689e933e31ee9286edad Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 14 Jul 2024 12:31:09 -0400 Subject: [PATCH 14/21] [src/lib/cli_parser.rs] Split `add_argument` into own function `add_arguments` ; `parse_args` cleanup so `return` is unnecessary --- src/lib/cli_parser.rs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index dd4980b5..edab7523 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -159,7 +159,12 @@ pub fn create_cli(global_config: &GlobalConfig) -> CliSpec { })) .add_command("makers") .add_subcommand(vec!["cargo", "make"]) - .add_subcommand(vec!["cargo-make", "make"]) // done by cargo + .add_subcommand(vec!["cargo-make", "make"]); // done by cargo + add_arguments(spec, default_task_name, default_log_level) +} + +fn add_arguments(spec: CliSpec, default_task_name: &str, default_log_level: &str) -> CliSpec { + spec .add_argument(Argument { name: "help".to_string(), key: vec!["--help".to_string(), "-h".to_string()], @@ -452,9 +457,7 @@ pub fn create_cli(global_config: &GlobalConfig) -> CliSpec { help: Some(ArgumentHelp::Text( "The task to execute, potentially including arguments which can be accessed in the task itself.".to_string(), )), - })); - - spec + })) } pub fn parse_args( @@ -474,20 +477,20 @@ pub fn parse_args( // generate help text let help_text = cliparser::help(&spec); println!("{}", help_text); - return Err(std::process::ExitCode::SUCCESS.into()); + Err(CargoMakeError::ExitCode(std::process::ExitCode::SUCCESS)) } else if cli_parsed.arguments.contains("version") { // generate version text let version_text = cliparser::version(&spec); println!("{}", version_text); - return Err(std::process::ExitCode::SUCCESS.into()); + Err(CargoMakeError::ExitCode(std::process::ExitCode::SUCCESS)) + } else { + Ok(get_args( + &cli_parsed, + &global_config, + command_name, + sub_command, + )) } - - return Ok(get_args( - &cli_parsed, - &global_config, - command_name, - sub_command, - )); } pub fn parse( From 8769d473bef8f65f3411783e6614a1d95c8ef631 Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Sun, 14 Jul 2024 17:48:42 +0000 Subject: [PATCH 15/21] readme --- CHANGELOG.md | 2 +- Cargo.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05646c9d..e80c3cef 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ### v0.37.14 -* Fix: fix the --skip-init-end-tasks argument #1108 +* Fix: fix the --skip-init-end-tasks argument #1108 (thanks @06393993) ### v0.37.13 (2024-07-07) diff --git a/Cargo.lock b/Cargo.lock index 60d35463..6e85cd52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" +checksum = "5208975e568d83b6b05cc0a063c8e7e9acc2b43bee6da15616a5b73e109d7437" [[package]] name = "cfg-if" From 5247eafa9ccb00115fddc1461eb2f2479fac2bdd Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Sun, 14 Jul 2024 17:50:50 +0000 Subject: [PATCH 16/21] lock --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e85cd52..95bbfeb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,9 +104,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "bzip2" @@ -204,9 +204,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.105" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5208975e568d83b6b05cc0a063c8e7e9acc2b43bee6da15616a5b73e109d7437" +checksum = "9711f33475c22aab363b05564a17d7b789bf3dfec5ebabb586adee56f0e271b5" [[package]] name = "cfg-if" @@ -1241,9 +1241,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", "core-foundation", @@ -1254,9 +1254,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -1370,9 +1370,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.69" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -1393,18 +1393,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", @@ -1432,9 +1432,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "tinyvec" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6b6a2fb3a985e99cebfaefa9faa3024743da73304ca1c683a36429613d3d22" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1468,9 +1468,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap 2.2.6", "serde", From 01197547f71407c76e630fd21718047ff2f4e793 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:21:33 -0400 Subject: [PATCH 17/21] Merge branch '0.37.14' into cargo-make-as-library --- src/lib/cli_commands/diff_steps.rs | 5 +- src/lib/cli_commands/print_steps.rs | 3 +- src/lib/cli_commands/print_steps_test.rs | 8 +- src/lib/cli_test.rs | 4 +- src/lib/error.rs | 19 +-- src/lib/execution_plan.rs | 164 +++++++++++++---------- src/lib/execution_plan_test.rs | 78 ++++++----- src/lib/runner.rs | 17 +-- src/lib/runner_test.rs | 4 +- 9 files changed, 173 insertions(+), 129 deletions(-) diff --git a/src/lib/cli_commands/diff_steps.rs b/src/lib/cli_commands/diff_steps.rs index 3c3b2045..fdfc6db0 100644 --- a/src/lib/cli_commands/diff_steps.rs +++ b/src/lib/cli_commands/diff_steps.rs @@ -9,7 +9,6 @@ mod diff_steps_test; use crate::command; use crate::error::CargoMakeError; -use crate::execution_plan::create as create_execution_plan; use crate::execution_plan::ExecutionPlanBuilder; use crate::io::{create_file, delete_file}; use crate::types::{CliArgs, Config, CrateInfo, ExecutionPlan}; @@ -49,7 +48,7 @@ pub(crate) fn run( skip_tasks_pattern: skip_tasks_pattern.as_ref(), ..ExecutionPlanBuilder::new(internal_config, &task) } - .build(); + .build()?; let external_execution_plan = ExecutionPlanBuilder { crate_info: Some(crateinfo), @@ -58,7 +57,7 @@ pub(crate) fn run( skip_tasks_pattern: skip_tasks_pattern.as_ref(), ..ExecutionPlanBuilder::new(external_config, &task) } - .build(); + .build()?; let internal_file = create_file( &move |file: &mut File| write_as_string(&internal_execution_plan, &file), diff --git a/src/lib/cli_commands/print_steps.rs b/src/lib/cli_commands/print_steps.rs index a09f4a07..e3263d16 100644 --- a/src/lib/cli_commands/print_steps.rs +++ b/src/lib/cli_commands/print_steps.rs @@ -8,7 +8,6 @@ mod print_steps_test; use crate::error::CargoMakeError; -use crate::execution_plan::create as create_execution_plan; use std::io; use crate::execution_plan::ExecutionPlanBuilder; @@ -104,7 +103,7 @@ pub fn print( skip_init_end_tasks, ..ExecutionPlanBuilder::new(&config, &task) } - .build(); + .build()?; debug!("Created execution plan: {:#?}", &execution_plan); let print_format = get_format_type(&output_format); diff --git a/src/lib/cli_commands/print_steps_test.rs b/src/lib/cli_commands/print_steps_test.rs index 2d0ce0a4..82a63f0f 100644 --- a/src/lib/cli_commands/print_steps_test.rs +++ b/src/lib/cli_commands/print_steps_test.rs @@ -41,7 +41,7 @@ fn print_default_format() { "test", "default", false, - None, + &None, &CrateInfo::new(), false, ) @@ -69,7 +69,7 @@ fn print_task_not_found() { "test", "default", false, - None, + &None, &CrateInfo::new(), false, ) @@ -96,7 +96,7 @@ fn print_task_not_found_but_skipped() { "test", "default", false, - Some("test".to_string()), + &Some("test".to_string()), &CrateInfo::new(), false, ) @@ -160,7 +160,7 @@ fn print_skip_init_end_tasks() { "entry", "default", false, - None, + &None, &CrateInfo::new(), true, ) diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index e193cb41..bc31986b 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -724,11 +724,11 @@ fn run_set_task_var_args() { Some(vec![ "cargo", "make", "empty", "abc", "-p", "foo/bar/", "def", ]), - ); + ).unwrap(); envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); - run(&cli_args.unwrap(), &global_config).unwrap(); + run(&cli_args, &global_config).unwrap(); assert_eq!( envmnt::get_or_panic("CARGO_MAKE_TASK_ARGS"), diff --git a/src/lib/error.rs b/src/lib/error.rs index f6b94c8e..235ffdf2 100644 --- a/src/lib/error.rs +++ b/src/lib/error.rs @@ -19,29 +19,32 @@ pub enum CargoMakeError { #[strum(to_string = "Detected cycle while resolving alias {0}: {1}")] AliasCycle(String, String) = 101, + #[strum(to_string = "Circular reference found for task: {0:#?}")] + CircularReference(String) = 102, + #[strum(to_string = "Unable to run, minimum required version is: {0}")] - VersionTooOld(String) = 102, + VersionTooOld(String) = 103, #[strum(to_string = "Error while executing command, unable to extract exit code.")] - ExitCodeValidation = 103, + ExitCodeValidation = 104, #[strum(to_string = "Error while executing command, exit code: {0}")] - ExitCodeError(i32) = 104, + ExitCodeError(i32) = 105, #[strum(to_string = "Unable to parse internal descriptor: {0}")] - DescriptorParseFailed(String) = 105, + DescriptorParseFailed(String) = 106, #[strum(to_string = "Unable to parse external file: {0:#?}, {1}")] - ParseFileFailed(String, String) = 106, + ParseFileFailed(String, String) = 107, #[strum(to_string = "{0}")] - Arity(&'static str) = 107, + Arity(&'static str) = 108, #[strum(to_string = "{0}")] - MethodCallRestriction(&'static str) = 108, + MethodCallRestriction(&'static str) = 109, #[strum(to_string = "Task {0:#?} is {1}")] - TaskIs(String, &'static str), + TaskIs(String, &'static str) = 110, #[strum(to_string = "{0}")] NotFound(String) = 404, diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 2bc58b0c..31547448 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -8,6 +8,7 @@ mod execution_plan_test; use crate::environment; +use crate::error::CargoMakeError; use crate::logger; use crate::profile; use crate::proxy_task::create_proxy_task; @@ -23,10 +24,11 @@ use std::env; use std::path::Path; /// Resolve aliases recursively until a task without alias is found. -/// -/// # Panics -/// if there is a cycle in the alias chain. -fn get_task_name_recursive(config: &Config, name: &str, seen: &mut Vec) -> Option { +fn get_task_name_recursive( + config: &Config, + name: &str, + seen: &mut Vec, +) -> Result { seen.push(name.to_string()); match config.tasks.get(name) { @@ -37,13 +39,16 @@ fn get_task_name_recursive(config: &Config, name: &str, seen: &mut Vec) Some(ref alias) if seen.contains(alias) => { let chain = seen.join(" -> "); error!("Detected cycle while resolving alias {}: {}", &name, chain); - panic!("Detected cycle while resolving alias {}: {}", &name, chain); + return Err(CargoMakeError::AliasCycle(name.to_string(), chain)); } Some(ref alias) => get_task_name_recursive(config, alias, seen), - None => Some(name.to_string()), + None => Ok(name.to_string()), } } - None => None, + None => Err(CargoMakeError::NotFound(format!( + "Task {:#?} not found", + name + ))), } } @@ -51,7 +56,7 @@ fn get_task_name_recursive(config: &Config, name: &str, seen: &mut Vec) /// /// # Panics /// if there is a cycle in the alias chain. -pub(crate) fn get_actual_task_name(config: &Config, name: &str) -> Option { +pub(crate) fn get_actual_task_name(config: &Config, name: &str) -> Result { let mut seen = Vec::new(); get_task_name_recursive(config, name, &mut seen) @@ -61,60 +66,61 @@ pub(crate) fn get_actual_task_name(config: &Config, name: &str) -> Option Task { - match get_optional_normalized_task(config, name, support_alias) { - Some(task) => task, - None => { - error!("Task {} not found", &name); - panic!("Task {} not found", &name); - } - } +pub(crate) fn get_normalized_task( + config: &Config, + name: &str, + support_alias: bool, +) -> Result { + get_optional_normalized_task(config, name, support_alias) } /// Resolves alias and normalizes task. /// /// # Panics /// if there is a cycle in the alias chain. -fn get_optional_normalized_task(config: &Config, name: &str, support_alias: bool) -> Option { - let actual_task_name_option = if support_alias { +fn get_optional_normalized_task( + config: &Config, + name: &str, + support_alias: bool, +) -> Result { + let actual_task_name = if support_alias { get_actual_task_name(config, name) } else { - Some(name.to_string()) - }; + Ok(name.to_string()) + }?; - match actual_task_name_option { - Some(actual_task_name) => match config.tasks.get(&actual_task_name) { - Some(task_config) => { - let mut clone_task = task_config.clone(); - let mut normalized_task = clone_task.get_normalized_task(); - - normalized_task = match normalized_task.extend { - Some(ref extended_task_name) => { - let mut extended_task = - get_normalized_task(config, extended_task_name, support_alias); - - if let Some(ref env) = normalized_task.env { - if env.len() == 2 - && env.contains_key("CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE") - && env.contains_key( - "CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY", - ) - { - normalized_task.env = None; - } + match config.tasks.get(&actual_task_name) { + Some(task_config) => { + let mut clone_task = task_config.clone(); + let mut normalized_task = clone_task.get_normalized_task(); + + normalized_task = match normalized_task.extend { + Some(ref extended_task_name) => { + let mut extended_task = + get_normalized_task(config, extended_task_name, support_alias)?; + + if let Some(ref env) = normalized_task.env { + if env.len() == 2 + && env.contains_key("CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE") + && env + .contains_key("CARGO_MAKE_CURRENT_TASK_INITIAL_MAKEFILE_DIRECTORY") + { + normalized_task.env = None; } - extended_task.extend(&normalized_task); - - extended_task } - None => normalized_task, - }; + extended_task.extend(&normalized_task); - Some(normalized_task) - } - None => None, - }, - None => None, + extended_task + } + None => normalized_task, + }; + + Ok(normalized_task) + } + None => Err(CargoMakeError::NotFound(format!( + "Task {:#?} not found", + name + ))), } } @@ -301,11 +307,11 @@ fn is_workspace_flow( // determine if workspace flow is explicitly set and enabled in the requested task let (task_set_workspace, task_enable_workspace) = match get_optional_normalized_task(config, task, true) { - Some(normalized_task) => match normalized_task.workspace { + Ok(normalized_task) => match normalized_task.workspace { Some(enable_workspace) => (true, enable_workspace), None => (false, false), }, - None => (false, false), + Err(_) => (false, false), }; // if project is not a workspace or if workspace is disabled via cli, return no workspace flow @@ -337,11 +343,11 @@ fn create_for_step( root: bool, allow_private: bool, skip_tasks_pattern: Option<&Regex>, -) { +) -> Result<(), CargoMakeError> { if let Some(skip_tasks_pattern_regex) = skip_tasks_pattern { if skip_tasks_pattern_regex.is_match(&task.name) { debug!("Skipping task: {} due to skip pattern.", &task.name); - return; + return Ok(()); } } @@ -371,10 +377,10 @@ fn create_for_step( steps.push(step); task_names.insert(task.to_string()); - return; + return Ok(()); } - let task_config = get_normalized_task(config, &task.name, true); + let task_config = get_normalized_task(config, &task.name, true)?; debug!("Normalized Task: {} config: {:#?}", &task, &task_config); @@ -398,7 +404,7 @@ fn create_for_step( false, true, skip_tasks_pattern, - ); + )?; } } _ => debug!("No dependencies found for task: {}", &task), @@ -411,17 +417,22 @@ fn create_for_step( }); task_names.insert(task.to_string()); } else if root { - error!("Circular reference found for task: {}", &task); + return Err(CargoMakeError::CircularReference(format!("{}", task))); } } + Ok(()) } else { error!("Task {} is private", &task); - panic!("Task {} is private", &task); + return Err(CargoMakeError::TaskIs(format!("{}", task), "private")); } } -fn add_predefined_step(config: &Config, task: &str, steps: &mut Vec) { - let task_config = get_normalized_task(config, task, false); +fn add_predefined_step( + config: &Config, + task: &str, + steps: &mut Vec, +) -> Result<(), CargoMakeError> { + let task_config = get_normalized_task(config, task, false)?; let add = !task_config.disabled.unwrap_or(false); if add { @@ -430,6 +441,7 @@ fn add_predefined_step(config: &Config, task: &str, steps: &mut Vec) { config: task_config, }); } + Ok(()) } #[derive(Clone, Debug)] @@ -458,7 +470,7 @@ impl<'a> ExecutionPlanBuilder<'a> { } } - pub fn build(&self) -> ExecutionPlan { + pub fn build(&self) -> Result { let Self { config, task, @@ -477,12 +489,20 @@ impl<'a> ExecutionPlanBuilder<'a> { if !skip_init_end_tasks { match config.config.legacy_migration_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), - None => debug!("Legacy migration task not defined."), + Some(ref task) => add_predefined_step(config, task, &mut steps)?, + None => { + return Err(CargoMakeError::NotFound(String::from( + "Legacy migration task not defined.", + ))) + } }; match config.config.init_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), - None => debug!("Init task not defined."), + Some(ref task) => add_predefined_step(config, task, &mut steps)?, + None => { + return Err(CargoMakeError::NotFound(String::from( + "Init task not defined.", + ))) + } }; } @@ -511,7 +531,7 @@ impl<'a> ExecutionPlanBuilder<'a> { true, allow_private, skip_tasks_pattern, - ); + )?; } } else { debug!("Skipping task: {} due to skip pattern.", &task); @@ -520,11 +540,15 @@ impl<'a> ExecutionPlanBuilder<'a> { if !skip_init_end_tasks { // always add end task even if already executed due to some dependency match config.config.end_task { - Some(ref task) => add_predefined_step(config, task, &mut steps), - None => debug!("Ent task not defined."), + Some(ref task) => add_predefined_step(config, task, &mut steps)?, + None => { + return Err(CargoMakeError::NotFound(String::from( + "Ent task not defined.", + ))) + } }; } - ExecutionPlan { steps } + Ok(ExecutionPlan { steps }) } } diff --git a/src/lib/execution_plan_test.rs b/src/lib/execution_plan_test.rs index c455ebbb..86447afd 100644 --- a/src/lib/execution_plan_test.rs +++ b/src/lib/execution_plan_test.rs @@ -487,7 +487,7 @@ fn is_workspace_flow_true_default() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); assert!(workspace_flow); } @@ -518,7 +518,7 @@ fn is_workspace_flow_false_in_config() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); assert!(!workspace_flow); } @@ -549,7 +549,7 @@ fn is_workspace_flow_true_in_config() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); assert!(workspace_flow); } @@ -578,7 +578,7 @@ fn is_workspace_flow_true_in_task() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); assert!(workspace_flow); } @@ -606,7 +606,7 @@ fn is_workspace_flow_default_false_in_task_and_sub_flow() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true); assert!(!workspace_flow); } @@ -635,7 +635,7 @@ fn is_workspace_flow_true_in_task_and_sub_flow() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true); assert!(workspace_flow); } @@ -664,7 +664,7 @@ fn is_workspace_flow_false_in_task_and_sub_flow() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, true); assert!(!workspace_flow); } @@ -689,7 +689,7 @@ fn is_workspace_flow_task_not_defined() { plugins: None, }; - let workspace_flow = is_workspace_flow(&config, "notfound", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "notfound", false, &crate_info, false); assert!(workspace_flow); } @@ -711,7 +711,7 @@ fn is_workspace_flow_no_workspace() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); assert!(!workspace_flow); } @@ -740,7 +740,7 @@ fn is_workspace_flow_disabled_via_cli() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", true, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", true, &crate_info, false); assert!(!workspace_flow); } @@ -769,7 +769,7 @@ fn is_workspace_flow_disabled_via_task() { }; config.tasks.insert("test".to_string(), task); - let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false).unwrap(); + let workspace_flow = is_workspace_flow(&config, "test", false, &crate_info, false); assert!(!workspace_flow); } @@ -799,7 +799,8 @@ fn create_single() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -832,7 +833,8 @@ fn create_single_disabled() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "end"); @@ -861,7 +863,9 @@ fn create_single_private() { config.tasks.insert("test-private".to_string(), task); - ExecutionPlanBuilder::new(&config, "test-private").build(); + ExecutionPlanBuilder::new(&config, "test-private") + .build() + .unwrap(); } #[test] @@ -890,7 +894,8 @@ fn create_single_allow_private() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test-private") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test-private"); @@ -928,7 +933,8 @@ fn create_with_dependencies() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "task_dependency"); @@ -970,7 +976,8 @@ fn create_with_foreign_dependencies_directory() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1017,7 +1024,8 @@ fn create_with_foreign_dependencies_filename() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1064,7 +1072,8 @@ fn create_with_foreign_dependencies_file_and_directory() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); @@ -1109,7 +1118,8 @@ fn create_with_dependencies_sub_flow() { sub_flow: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "task_dependency"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -1147,7 +1157,8 @@ fn create_disabled_task_with_dependencies() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 2); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "end"); @@ -1185,7 +1196,8 @@ fn create_with_dependencies_disabled() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "test"); @@ -1298,7 +1310,8 @@ fn create_platform_disabled() { allow_private: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 0); } @@ -1337,7 +1350,8 @@ fn create_with_dependencies_and_skip_filter() { skip_tasks_pattern: Some(&skip_filter), ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 4); assert_eq!(execution_plan.steps[0].name, "init"); assert_eq!(execution_plan.steps[1].name, "task_dependency"); @@ -1362,13 +1376,14 @@ fn create_workspace() { config.tasks.insert("test".to_string(), task); env::set_current_dir("./examples/workspace").unwrap(); - let crateinfo = environment::crateinfo::load(); + let crateinfo = environment::crateinfo::load().unwrap(); let execution_plan = ExecutionPlanBuilder { allow_private: true, crate_info: Some(&crateinfo), ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "workspace"); @@ -1391,14 +1406,15 @@ fn create_noworkspace() { config.tasks.insert("test".to_string(), task); env::set_current_dir("./examples/workspace").unwrap(); - let crateinfo = environment::crateinfo::load(); + let crateinfo = environment::crateinfo::load().unwrap(); let execution_plan = ExecutionPlanBuilder { disable_workspace: true, allow_private: true, crate_info: Some(&crateinfo), ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); env::set_current_dir("../../").unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "test"); @@ -1419,7 +1435,8 @@ fn create_task_extends_empty_env_bug_verification() { disable_workspace: true, ..ExecutionPlanBuilder::new(&config, "task2") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 3); @@ -1617,7 +1634,8 @@ fn respect_skip_init_end_tasks() { skip_init_end_tasks: true, ..ExecutionPlanBuilder::new(&config, "test") } - .build(); + .build() + .unwrap(); assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "test"); } diff --git a/src/lib/runner.rs b/src/lib/runner.rs index edc17837..6e23c7c6 100755 --- a/src/lib/runner.rs +++ b/src/lib/runner.rs @@ -12,11 +12,18 @@ #[path = "runner_test.rs"] mod runner_test; +use std::cell::RefCell; +use std::rc::Rc; +use std::thread; +use std::time::SystemTime; + +use indexmap::IndexMap; +use regex::Regex; + use crate::command; use crate::condition; use crate::environment; use crate::error::CargoMakeError; -use crate::execution_plan::create as create_execution_plan; use crate::execution_plan::ExecutionPlanBuilder; use crate::functions; use crate::installer; @@ -31,12 +38,6 @@ use crate::types::{ MaybeArray, RunTaskInfo, RunTaskName, RunTaskOptions, RunTaskRoutingInfo, Step, Task, TaskWatchOptions, }; -use indexmap::IndexMap; -use regex::Regex; -use std::cell::RefCell; -use std::rc::Rc; -use std::thread; -use std::time::SystemTime; fn do_in_task_working_directory(step: &Step, mut action: F) -> Result<(), CargoMakeError> where @@ -606,7 +607,7 @@ pub(crate) fn run_flow( skip_init_end_tasks: flow_info.skip_init_end_tasks, ..ExecutionPlanBuilder::new(&flow_info.config, &flow_info.task) } - .build(); + .build()?; debug!("Created execution plan: {:#?}", &execution_plan); run_task_flow(&flow_info, flow_state, &execution_plan)?; diff --git a/src/lib/runner_test.rs b/src/lib/runner_test.rs index dbd2d465..38dd1164 100755 --- a/src/lib/runner_test.rs +++ b/src/lib/runner_test.rs @@ -2574,7 +2574,7 @@ fn run_flow_skip_init_end_tasks() { cli_arguments: None, }; - run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false).unwrap(); // Test with only end_task existing. let flow_info = { @@ -2586,5 +2586,5 @@ fn run_flow_skip_init_end_tasks() { flow_info }; - run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false); + run_flow(&flow_info, Rc::new(RefCell::new(FlowState::new())), false).unwrap(); } From 4564d61247f258c61cc3f9b3cd1a72c28d64b5a0 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 14 Jul 2024 17:34:14 -0400 Subject: [PATCH 18/21] [src/lib/execution_plan.rs] Comment out within `build`: `Err(CargoMakeError::NotFound` on `skip_init_end_tasks` & `skip_init_end_tasks` & `end_task` --- src/lib/cli_test.rs | 3 ++- src/lib/execution_plan.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index bc31986b..fc43d923 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -724,7 +724,8 @@ fn run_set_task_var_args() { Some(vec![ "cargo", "make", "empty", "abc", "-p", "foo/bar/", "def", ]), - ).unwrap(); + ) + .unwrap(); envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 31547448..6292d707 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -491,17 +491,17 @@ impl<'a> ExecutionPlanBuilder<'a> { match config.config.legacy_migration_task { Some(ref task) => add_predefined_step(config, task, &mut steps)?, None => { - return Err(CargoMakeError::NotFound(String::from( + /* return Err(CargoMakeError::NotFound(String::from( "Legacy migration task not defined.", - ))) + ))) */ } }; match config.config.init_task { Some(ref task) => add_predefined_step(config, task, &mut steps)?, None => { - return Err(CargoMakeError::NotFound(String::from( + /* return Err(CargoMakeError::NotFound(String::from( "Init task not defined.", - ))) + ))) */ } }; } @@ -542,9 +542,9 @@ impl<'a> ExecutionPlanBuilder<'a> { match config.config.end_task { Some(ref task) => add_predefined_step(config, task, &mut steps)?, None => { - return Err(CargoMakeError::NotFound(String::from( + /* return Err(CargoMakeError::NotFound(String::from( "Ent task not defined.", - ))) + ))) */ } }; } From 6f4f4f73f27ee2096e2ecf28ed4e1fc21266730f Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Sun, 14 Jul 2024 22:36:17 -0400 Subject: [PATCH 19/21] [src/lib/cli_{parser,parser_test,test}.rs] Pass around a `CliSpec` to enable library authors to expand the spec (* might need some post-processing) --- src/lib/cli_parser.rs | 43 +++++++++++++++++++++----------------- src/lib/cli_parser_test.rs | 26 ++++++++++++++++++++--- src/lib/cli_test.rs | 23 ++++++++++++++++++-- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/lib/cli_parser.rs b/src/lib/cli_parser.rs index edab7523..e14f9883 100644 --- a/src/lib/cli_parser.rs +++ b/src/lib/cli_parser.rs @@ -135,7 +135,7 @@ fn get_args( cli_args } -pub fn create_cli(global_config: &GlobalConfig) -> CliSpec { +pub fn create_cli(global_config: &GlobalConfig, mut spec: CliSpec, default_meta: bool) -> CliSpec { let default_task_name = match global_config.default_task_name { Some(ref value) => value.as_str(), None => &DEFAULT_TASK_NAME, @@ -145,21 +145,21 @@ pub fn create_cli(global_config: &GlobalConfig) -> CliSpec { None => &DEFAULT_LOG_LEVEL, }; - let mut spec = CliSpec::new(); - - spec = spec - .set_meta_info(Some(CliSpecMetaInfo { - author: Some(AUTHOR.to_string()), - version: Some(VERSION.to_string()), - description: Some(DESCRIPTION.to_string()), - project: Some("cargo-make".to_string()), - help_post_text: Some( - "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), - ), - })) - .add_command("makers") - .add_subcommand(vec!["cargo", "make"]) - .add_subcommand(vec!["cargo-make", "make"]); // done by cargo + if default_meta { + spec = spec + .set_meta_info(Some(CliSpecMetaInfo { + author: Some(AUTHOR.to_string()), + version: Some(VERSION.to_string()), + description: Some(DESCRIPTION.to_string()), + project: Some("cargo-make".to_string()), + help_post_text: Some( + "See more info at: https://github.com/sagiegurari/cargo-make".to_string(), + ), + })) + .add_command("makers") + .add_subcommand(vec!["cargo", "make"]) + .add_subcommand(vec!["cargo-make", "make"]); // done by cargo + } add_arguments(spec, default_task_name, default_log_level) } @@ -465,9 +465,8 @@ pub fn parse_args( command_name: &str, sub_command: bool, args: Option>, + spec: CliSpec, ) -> Result { - let spec = create_cli(&global_config); - let cli_parsed = match args { Some(args_vec) => cliparser::parse(&args_vec, &spec), None => cliparser::parse_process(&spec), @@ -498,7 +497,13 @@ pub fn parse( command_name: &str, sub_command: bool, ) -> Result { - parse_args(global_config, command_name, sub_command, None) + parse_args( + global_config, + command_name, + sub_command, + None, + create_cli(&global_config, CliSpec::new(), true), + ) } fn to_owned_vec(vec_option: Option<&Vec>) -> Option> { diff --git a/src/lib/cli_parser_test.rs b/src/lib/cli_parser_test.rs index 1b64123b..fc53e476 100644 --- a/src/lib/cli_parser_test.rs +++ b/src/lib/cli_parser_test.rs @@ -3,7 +3,13 @@ use super::*; fn default_parse_cli_args(mut args: Vec<&str>) -> Result { let global_config = GlobalConfig::new(); args.insert(0, "makers"); - parse_args(&global_config, "makers", false, Some(args)) + parse_args( + &global_config, + "makers", + false, + Some(args), + create_cli(&global_config, CliSpec::new(), true), + ) } fn default_parsed_cli_args() -> CliArgs { @@ -55,7 +61,14 @@ fn assert_cli_args(cli_args_ref1: &CliArgs, cli_args_ref2: &CliArgs) { #[test] fn parse_args_makers() { let global_config = GlobalConfig::new(); - let cli_args = parse_args(&global_config, "makers", false, Some(vec!["makers"])).unwrap(); + let cli_args = parse_args( + &global_config, + "makers", + false, + Some(vec!["makers"]), + create_cli(&global_config, CliSpec::new(), true), + ) + .unwrap(); let expected = default_parsed_cli_args(); @@ -65,7 +78,14 @@ fn parse_args_makers() { #[test] fn parse_args_cargo_make() { let global_config = GlobalConfig::new(); - let cli_args = parse_args(&global_config, "make", true, Some(vec!["cargo", "make"])).unwrap(); + let cli_args = parse_args( + &global_config, + "make", + true, + Some(vec!["cargo", "make"]), + create_cli(&global_config, CliSpec::new(), true), + ) + .unwrap(); let mut expected = default_parsed_cli_args(); expected.command = "cargo make".to_string(); diff --git a/src/lib/cli_test.rs b/src/lib/cli_test.rs index fc43d923..53c72ea4 100644 --- a/src/lib/cli_test.rs +++ b/src/lib/cli_test.rs @@ -1,4 +1,6 @@ use super::*; +use crate::cli_parser::create_cli; +use cliparser::types::CliSpec; use std::env; use std::path::Path; @@ -399,8 +401,13 @@ fn run_cwd_task_not_found() { #[test] fn run_bad_subcommand() { let global_config = GlobalConfig::new(); - let cli_args = - cli_parser::parse_args(&global_config, &"make".to_string(), true, Some(vec!["bad"])); + let cli_args = cli_parser::parse_args( + &global_config, + &"make".to_string(), + true, + Some(vec!["bad"]), + create_cli(&global_config, cliparser::types::CliSpec::new(), true), + ); assert_eq!( format!("{:?}", &cli_args.err().unwrap()), @@ -430,6 +437,7 @@ fn run_valid() { "arg2", "arg3", ]), + create_cli(&global_config, CliSpec::new(), true), ) .unwrap(); @@ -448,6 +456,7 @@ fn run_with_global_config() { &"make".to_string(), true, Some(vec!["cargo", "make"]), + create_cli(&global_config, CliSpec::new(), true), ) .unwrap(); @@ -473,6 +482,7 @@ fn run_log_level_override() { "error", "-v", ]), + create_cli(&global_config, CliSpec::new(), true), ) .unwrap(); @@ -501,6 +511,7 @@ fn run_set_env_values() { "-t", "empty", ]), + create_cli(&global_config, CliSpec::new(), true), ) .unwrap(); @@ -532,6 +543,7 @@ fn run_set_env_via_file() { "-t", "empty", ]), + create_cli(&global_config, CliSpec::new(), true), ); envmnt::set("ENV1_TEST", "EMPTY"); @@ -568,6 +580,7 @@ fn run_set_env_both() { "-t", "empty", ]), + create_cli(&global_config, CliSpec::new(), true), ); envmnt::set("ENV1_TEST", "EMPTY"); @@ -611,6 +624,7 @@ fn run_print_only() { "--print-steps", "--experimental", ]), + create_cli(&global_config, CliSpec::new(), true), ); run(&cli_args.unwrap(), &global_config).unwrap(); @@ -636,6 +650,7 @@ fn run_diff_steps() { "--no-workspace", "--diff-steps", ]), + create_cli(&global_config, CliSpec::new(), true), ); run(&cli_args.unwrap(), &global_config).unwrap(); @@ -656,6 +671,7 @@ fn run_protected_flow_example() { "--makefile", "./examples/on_error.toml", ]), + create_cli(&global_config, CliSpec::new(), true), ); run(&cli_args.unwrap(), &global_config).unwrap(); @@ -675,6 +691,7 @@ fn run_no_task_args() { "--disable-check-for-updates", "empty", ]), + create_cli(&global_config, CliSpec::new(), true), ); envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); @@ -701,6 +718,7 @@ fn run_set_task_args() { "arg2", "arg3", ]), + create_cli(&global_config, CliSpec::new(), true), ); envmnt::set("CARGO_MAKE_TASK_ARGS", "EMPTY"); @@ -724,6 +742,7 @@ fn run_set_task_var_args() { Some(vec![ "cargo", "make", "empty", "abc", "-p", "foo/bar/", "def", ]), + create_cli(&global_config, CliSpec::new(), true), ) .unwrap(); From 1b485dc8c884e69f7c7f167ebf578df9900867a2 Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Wed, 17 Jul 2024 08:21:27 +0000 Subject: [PATCH 20/21] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e80c3cef..d5971d90 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### v0.37.14 * Fix: fix the --skip-init-end-tasks argument #1108 (thanks @06393993) +* Enhancement: Support using cargo make as library #1112 (thanks @SamuelMarks) ### v0.37.13 (2024-07-07) From 3f11e8a437a735bcdad0022422ee36bb45c5e491 Mon Sep 17 00:00:00 2001 From: sagie gur ari Date: Wed, 17 Jul 2024 11:03:44 +0000 Subject: [PATCH 21/21] fix mac build --- src/lib/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/error.rs b/src/lib/error.rs index 235ffdf2..171a86f2 100644 --- a/src/lib/error.rs +++ b/src/lib/error.rs @@ -75,7 +75,7 @@ pub enum CargoMakeError { impl CargoMakeError { fn discriminant(&self) -> u16 { - unsafe { *<*const _>::from(self).cast::() } + unsafe { *(self as *const Self as *const u16) } } }