use crate::commands::{Command, CommandResult};
use crate::services::GitService;
use crate::app::{AppState, Action, reducer};
use crate::errors::CommandError;
use tracing::instrument;
pub struct CommitCommand {
pub message: String,
pub amend: bool,
pub author_name: Option<String>,
pub author_email: Option<String>,
}
impl Command for CommitCommand {
#[instrument(skip(self, git, state), fields(message = %self.message, amend = self.amend))]
fn execute(
&self,
git: &GitService,
state: &AppState,
) -> Result<CommandResult, CommandError> {
if self.message.trim().is_empty() {
let mut new_state = state.clone();
new_state = reducer(new_state, Action::SetStatusError(Some("Commit message is empty".into())));
return Ok(CommandResult::StateUpdate(new_state));
}
let mut new_state = state.clone();
new_state = reducer(new_state, Action::SetOpStatus(Some("committing…".into())));
match git.commit(
&state.repo_path,
&self.message,
self.amend,
self.author_name.as_deref(),
self.author_email.as_deref(),
) {
Ok(_) => {
let label = if self.amend { "Amended" } else { "Committed" };
new_state = reducer(
new_state,
Action::SetFeedback(Some(format!("{label} changes"))),
);
if self.amend {
new_state = reducer(
new_state,
Action::AppendOpLog("Amend done. Push with --force-with-lease (P) if this branch is shared.".into()),
);
new_state = reducer(
new_state,
Action::SetOpStatus(Some("Amend done. Push with --force-with-lease (P) if shared.".into())),
);
new_state = reducer(
new_state,
Action::ShowConfirm(
Box::new(Action::ForcePushAfterAmend),
"Amend completed. Force push to remote? (This rewrites history)".into()
),
);
}
new_state = reducer(new_state, Action::SetRefreshing(true));
new_state.commit_mode = false;
new_state.commit_input.clear();
new_state = reducer(new_state, Action::AppendOpLog(format!("{label} {}", self.message)));
}
Err(e) => {
new_state = reducer(new_state, Action::AppendOpLog(format!("commit error: {e}")));
new_state = reducer(new_state, Action::SetStatusError(Some(format!("commit error: {e}"))));
}
}
new_state = reducer(new_state, Action::SetOpStatus(None));
Ok(CommandResult::StateUpdate(new_state))
}
}