use crate::command::{CommandExecutor, CommandOutput, GitCommand};
use crate::error::Result;
use async_trait::async_trait;
use std::path::PathBuf;
#[derive(Debug, Clone, Default)]
pub struct CommitCommand {
pub executor: CommandExecutor,
pub message: Option<String>,
pub message_file: Option<PathBuf>,
pub all: bool,
pub amend: bool,
pub no_edit: bool,
pub allow_empty: bool,
pub allow_empty_message: bool,
pub signoff: bool,
pub no_verify: bool,
pub author: Option<String>,
pub date: Option<String>,
pub only_paths: Vec<String>,
pub quiet: bool,
pub verbose: bool,
}
impl CommitCommand {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn with_message(msg: impl Into<String>) -> Self {
let mut c = Self::new();
c.message = Some(msg.into());
c
}
pub fn message(&mut self, msg: impl Into<String>) -> &mut Self {
self.message = Some(msg.into());
self
}
pub fn message_file(&mut self, path: impl Into<PathBuf>) -> &mut Self {
self.message_file = Some(path.into());
self
}
pub fn all(&mut self) -> &mut Self {
self.all = true;
self
}
pub fn amend(&mut self) -> &mut Self {
self.amend = true;
self
}
pub fn no_edit(&mut self) -> &mut Self {
self.no_edit = true;
self
}
pub fn allow_empty(&mut self) -> &mut Self {
self.allow_empty = true;
self
}
pub fn allow_empty_message(&mut self) -> &mut Self {
self.allow_empty_message = true;
self
}
pub fn signoff(&mut self) -> &mut Self {
self.signoff = true;
self
}
pub fn no_verify(&mut self) -> &mut Self {
self.no_verify = true;
self
}
pub fn author(&mut self, a: impl Into<String>) -> &mut Self {
self.author = Some(a.into());
self
}
pub fn date(&mut self, d: impl Into<String>) -> &mut Self {
self.date = Some(d.into());
self
}
pub fn only(&mut self, path: impl Into<String>) -> &mut Self {
self.only_paths.push(path.into());
self
}
pub fn quiet(&mut self) -> &mut Self {
self.quiet = true;
self
}
pub fn verbose(&mut self) -> &mut Self {
self.verbose = true;
self
}
}
#[async_trait]
impl GitCommand for CommitCommand {
type Output = CommandOutput;
fn get_executor(&self) -> &CommandExecutor {
&self.executor
}
fn get_executor_mut(&mut self) -> &mut CommandExecutor {
&mut self.executor
}
fn build_command_args(&self) -> Vec<String> {
let mut args = vec!["commit".to_string()];
if self.all {
args.push("--all".into());
}
if self.amend {
args.push("--amend".into());
}
if self.no_edit {
args.push("--no-edit".into());
}
if self.allow_empty {
args.push("--allow-empty".into());
}
if self.allow_empty_message {
args.push("--allow-empty-message".into());
}
if self.signoff {
args.push("--signoff".into());
}
if self.no_verify {
args.push("--no-verify".into());
}
if self.quiet {
args.push("--quiet".into());
}
if self.verbose {
args.push("--verbose".into());
}
if let Some(a) = &self.author {
args.push(format!("--author={a}"));
}
if let Some(d) = &self.date {
args.push(format!("--date={d}"));
}
if let Some(m) = &self.message {
args.push("-m".into());
args.push(m.clone());
}
if let Some(f) = &self.message_file {
args.push("-F".into());
args.push(f.display().to_string());
}
if !self.only_paths.is_empty() {
args.push("--only".into());
args.push("--".into());
args.extend(self.only_paths.iter().cloned());
}
args
}
async fn execute(&self) -> Result<CommandOutput> {
self.execute_raw().await
}
}