git-gamble 2.13.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(opt: Cli) -> GambleResult<()> {
	let maybe_test_command = reformat_command(opt.test_command.clone());

	maybe_test_command
		.ok_or_else(|| {
			let invalid_test_command = opt.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(opt.repository_path.as_path(), opt.dry_run, opt.no_verify);

			let hook_gambled = if opt.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 opt.pass { tcr } else { trc };

					let command_choice = gamble_strategy(status);

					command_choice(&opt, &repository)
				})
		})
}

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