use std::path::Path;
use anyhow::{Result, bail};
pub enum RebaseOutcome {
Completed,
Conflicted,
}
pub fn continue_rebase(workdir: &Path) -> Result<RebaseOutcome> {
use std::process::Command;
let status = Command::new("git")
.current_dir(workdir)
.args(["rebase", "--continue"])
.env("GIT_EDITOR", "true")
.status()?;
if status.success() {
Ok(RebaseOutcome::Completed)
} else {
Ok(RebaseOutcome::Conflicted)
}
}
pub fn rebase(git_dir: &Path, workdir: &Path, upstream: &str) -> Result<RebaseOutcome> {
match super::run_git(
workdir,
&[
"rebase",
"--autostash",
"--update-refs",
"--rebase-merges",
upstream,
],
) {
Ok(()) => Ok(RebaseOutcome::Completed),
Err(e) => {
if rebase_is_in_progress(git_dir) {
Ok(RebaseOutcome::Conflicted)
} else {
Err(e)
}
}
}
}
#[cfg(test)]
pub fn rebase_onto(workdir: &Path, newbase: &str, upstream: &str) -> Result<()> {
super::run_git(
workdir,
&[
"rebase",
"--onto",
newbase,
upstream,
"--autostash",
"--update-refs",
],
)
}
pub fn rebase_abort(workdir: &Path) -> Result<()> {
super::run_git(workdir, &["rebase", "--abort"])
}
pub fn rebase_is_in_progress(git_dir: &Path) -> bool {
git_dir.join("rebase-merge").exists() || git_dir.join("rebase-apply").exists()
}
pub fn continue_rebase_or_abort(workdir: &Path) -> Result<()> {
match continue_rebase(workdir)? {
RebaseOutcome::Completed => Ok(()),
RebaseOutcome::Conflicted => {
let _ = rebase_abort(workdir);
bail!("Rebase failed with conflicts — aborted");
}
}
}