use anyhow::{bail, Result};
use std::process::Command;
use std::path::Path;
use std::fs;
use super::GitCli;
pub(crate) fn format_rebase_todo_line(action: &str, hash: &str, message: &str) -> String {
format!("{} {} {}", action, hash, message)
}
pub(crate) fn format_rebase_todo(entries: &[(String, String, String)]) -> String {
entries
.iter()
.map(|(action, hash, message)| format_rebase_todo_line(action, hash, message))
.collect::<Vec<_>>()
.join("\n")
}
pub(crate) fn write_rebase_todo_file(path: &Path, content: &str) -> Result<()> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
fs::write(path, content)?;
Ok(())
}
impl GitCli {
pub fn rebase_continue(
&self,
repo_path: &str,
message: Option<&str>,
author_name: Option<&str>,
author_email: Option<&str>,
) -> Result<()> {
if let Some(msg) = message {
let mut amend_cmd = Command::new("git");
amend_cmd.args(["-C", repo_path, "commit", "--amend", "--allow-empty", "-m", msg]);
if let Some(name) = author_name {
amend_cmd.env("GIT_AUTHOR_NAME", name).env("GIT_COMMITTER_NAME", name);
}
if let Some(email) = author_email {
amend_cmd.env("GIT_AUTHOR_EMAIL", email).env("GIT_COMMITTER_EMAIL", email);
}
let amend_output = amend_cmd.output()?;
if !amend_output.status.success() {
let stderr = String::from_utf8_lossy(&amend_output.stderr);
if !stderr.contains("nothing to commit") && !stderr.contains("no rebase in progress") {
bail!("git commit --amend failed: {}", stderr);
}
}
}
let mut cmd = Command::new("git");
cmd.args(["-C", repo_path, "rebase", "--continue"]);
if let Some(name) = author_name { cmd.env("GIT_AUTHOR_NAME", name).env("GIT_COMMITTER_NAME", name); }
if let Some(email) = author_email { cmd.env("GIT_AUTHOR_EMAIL", email).env("GIT_COMMITTER_EMAIL", email); }
cmd.env("GIT_EDITOR", "true");
let output = cmd.output()?;
if !output.status.success() {
bail!("git rebase --continue failed: {}", String::from_utf8_lossy(&output.stderr));
}
Ok(())
}
pub fn rebase_abort(&self, repo_path: &str) -> Result<()> {
let output = Command::new("git")
.args(["-C", repo_path, "rebase", "--abort"])
.output()?;
if !output.status.success() {
bail!("git rebase --abort failed: {}", String::from_utf8_lossy(&output.stderr));
}
Ok(())
}
pub fn rebase_skip(&self, repo_path: &str) -> Result<()> {
let output = Command::new("git")
.args(["-C", repo_path, "rebase", "--skip"])
.output()?;
if !output.status.success() {
bail!("git rebase --skip failed: {}", String::from_utf8_lossy(&output.stderr));
}
Ok(())
}
}