use anyhow::Result;
use git2::Repository;
use crate::branch;
use crate::core::repo::{self, Target};
use crate::core::msg;
use crate::core::weave;
use crate::git;
pub fn run(target: String, message: Option<String>) -> Result<()> {
let repo = repo::open_repo()?;
let resolved = repo::resolve_arg(
&repo,
&target,
&[repo::TargetKind::Branch, repo::TargetKind::Commit],
)?;
match resolved {
Target::Commit(hash) => reword_commit(&repo, &hash, message),
Target::Branch(name) => {
let new_name = match message {
Some(msg) => msg,
None => {
msg::input_with_placeholder("New branch name", &name, |s| {
if s.trim().is_empty() {
Err("Branch name cannot be empty")
} else {
Ok(())
}
})?
}
};
let new_name = new_name.trim().to_string();
if new_name == name {
return Ok(());
}
git::branch_validate_name(&new_name)?;
reword_branch(&repo, &name, &new_name)
}
_ => unreachable!(),
}
}
pub fn reword_commit(repo: &Repository, commit_hash: &str, message: Option<String>) -> Result<()> {
let workdir = repo::require_workdir(repo, "reword")?;
let commit_oid = repo.revparse_single(commit_hash)?.peel_to_commit()?.id();
weave::start_edit_rebase(repo, workdir, commit_oid)?;
if let Err(e) = git::commit_amend(workdir, message.as_deref()) {
let _ = git::rebase_abort(workdir);
return Err(e);
}
let new_hash = repo.head()?.peel_to_commit()?.id().to_string();
git::continue_rebase_or_abort(workdir)?;
msg::success(&format!(
"Updated commit message for `{}` (now `{}`)",
git::short_hash(commit_hash),
git::short_hash(&new_hash)
));
Ok(())
}
pub fn reword_branch(repo: &Repository, old_name: &str, new_name: &str) -> Result<()> {
let workdir = repo::require_workdir(repo, "rename branch")?;
git::branch_rename(workdir, old_name, new_name)?;
branch::warn_if_hidden(repo, new_name);
msg::success(&format!("Renamed branch `{}` to `{}`", old_name, new_name));
Ok(())
}
#[cfg(test)]
#[path = "reword_test.rs"]
mod tests;