git-gamble 2.14.1

blend TDD + TCR to make sure to develop the right thing 😌, baby step by baby step πŸ‘ΆπŸ¦Ά
Documentation
use crate::message::Message;

use super::cli::Cli;
use super::command_choice::tcr;
use super::command_choice::trc;
use super::gamble_result::GambleError;
use super::gamble_result::GambleResult;
use super::repository::Repository;

pub fn gamble(options: Cli) -> GambleResult<()> {
	let maybe_test_command = reformat_command(options.test_command.clone());

	maybe_test_command
		.ok_or_else(|| {
			let invalid_test_command = options.test_command.join(" ");

			log::error!("Can't parse test command \"{invalid_test_command}\"");

			GambleError {
				messages: vec![Message::Error(format!(
					"Can't parse test command \"{invalid_test_command}\""
				))],
				code: 1,
			}
		})
		.and_then(|test_command| {
			let repository = Repository::new(
				options.repository_path.as_path(),
				options.dry_run,
				options.no_verify,
			);

			let hook_gambled = if options.pass { "pass" } else { "fail" };
			repository
				.run_hook("pre-gamble", &[hook_gambled])
				.map_err(|error| {
					error.add_message(Message::Warn(
						"No tests have been run, and nothing has been committed or reverted"
							.to_string(),
					))
				})
				.and_then(|()| repository.command(&["add", "--all"]))
				.and_then(|()| repository.run_test_command(test_command))
				.and_then(|status| {
					let gamble_strategy = if options.pass { tcr } else { trc };

					let command_choice = gamble_strategy(status);

					command_choice(&options, &repository)
				})
		})
}

fn reformat_command(command: Vec<String>) -> Option<Vec<String>> {
	if command.len() == 1 {
		shlex::split(command[0].as_str())
	} else {
		Some(command)
	}
}