girt-core 2.3.0

Core modules for git-interactive-rebase-tool
Documentation
use std::ffi::OsString;

use pico_args::Arguments;

use crate::{exit::Exit, module::ExitStatus};

#[derive(Debug, Eq, PartialEq)]
pub(crate) enum Mode {
	Editor,
	Help,
	Version,
	License,
}

#[derive(Debug)]
pub(crate) struct Args {
	mode: Mode,
	todo_file_path: Option<String>,
}

impl Args {
	pub(crate) const fn mode(&self) -> &Mode {
		&self.mode
	}

	pub(crate) const fn todo_file_path(&self) -> &Option<String> {
		&self.todo_file_path
	}
}

impl TryFrom<Vec<OsString>> for Args {
	type Error = Exit;

	fn try_from(args: Vec<OsString>) -> Result<Self, Self::Error> {
		let mut pargs = Arguments::from_vec(args);

		let mode = if pargs.contains(["-h", "--help"]) {
			Mode::Help
		}
		else if pargs.contains(["-v", "--version"]) {
			Mode::Version
		}
		else if pargs.contains("--license") {
			Mode::License
		}
		else {
			Mode::Editor
		};

		let todo_file_path = pargs
			.opt_free_from_str()
			.map_err(|err| Exit::new(ExitStatus::StateError, err.to_string().as_str()))?;

		Ok(Self { mode, todo_file_path })
	}
}

#[cfg(test)]
mod tests {
	use super::*;

	fn create_args(args: &[&str]) -> Vec<OsString> {
		args.iter().map(OsString::from).collect()
	}

	#[test]
	fn mode_help() {
		assert_eq!(Args::try_from(create_args(&["-h"])).unwrap().mode(), &Mode::Help);
		assert_eq!(Args::try_from(create_args(&["--help"])).unwrap().mode(), &Mode::Help);
	}

	#[test]
	fn mode_version() {
		assert_eq!(Args::try_from(create_args(&["-v"])).unwrap().mode(), &Mode::Version);
		assert_eq!(
			Args::try_from(create_args(&["--version"])).unwrap().mode(),
			&Mode::Version
		);
	}

	#[test]
	fn mode_license() {
		assert_eq!(
			Args::try_from(create_args(&["--license"])).unwrap().mode(),
			&Mode::License
		);
	}

	#[test]
	fn todo_file_ok() {
		let args = Args::try_from(create_args(&["todofile"])).unwrap();
		assert_eq!(args.mode(), &Mode::Editor);
		assert_eq!(args.todo_file_path(), &Some(String::from("todofile")));
	}

	#[test]
	fn todo_file_missing() {
		let args = Args::try_from(create_args(&[])).unwrap();
		assert_eq!(args.mode(), &Mode::Editor);
		assert!(args.todo_file_path().is_none());
	}

	#[cfg(unix)]
	#[test]
	#[allow(unsafe_code)]
	fn todo_file_invalid() {
		let args = unsafe { vec![OsString::from(String::from_utf8_unchecked(vec![0xC3, 0x28]))] };
		_ = Args::try_from(args).unwrap_err();
	}
}