use crate::utils::errors::CustomError;
use std::path::PathBuf;
use std::process::{Command, Output};
pub fn branch_exists<P: AsRef<str>>(branch: P) -> Result<bool, CustomError> {
match git(&["show-ref", "--quiet", branch.as_ref()]) {
Ok(_) => Ok(true),
Err(err) =>
match err {
CustomError::ProcessFailed(Some(1), _, _, _) => Ok(false),
_ => Err(err)
}
}
}
pub fn checkout_worktree<P: AsRef<str>>(dir: &PathBuf, branch: P) -> Result<Output, CustomError> {
let dir_str = dir.to_str().ok_or(CustomError::Custom(dir.display().to_string() + " was not a UTF-8 string."))?;
git(&["worktree", "add", dir_str, branch.as_ref()])
}
pub fn new_worktree<P: AsRef<str>>(dir: &PathBuf, branch: P) -> Result<Output, CustomError> {
let dir_str = dir.to_str().ok_or(CustomError::Custom(dir.display().to_string() + " was not a UTF-8 string."))?;
git(&["worktree", "add", dir_str, "-b", branch.as_ref()])
}
pub fn checkout_new_or_existing_worktree<P: AsRef<str>>(dir: &PathBuf, branch: P) -> Result<Output, CustomError> {
if branch_exists(&branch)? {
checkout_worktree(dir, &branch)
} else {
new_worktree(dir, &branch)
}
}
pub fn is_valid_worktree(path: &PathBuf) -> bool {
path.exists() && path.join(".git").exists()
}
pub fn list_branches(pattern: &str) -> Result<Vec<String>, CustomError> {
let output = git(&["branch", "-l", &format!("{}*", pattern)])?;
let branches: Vec<String> = str::from_utf8(&output.stdout)?.to_string()
.lines()
.map(|line| line.trim_start_matches("* ").trim_start_matches("+ ").trim_start_matches(" ").trim_end_matches(" ").to_string())
.collect();
Ok(branches)
}
pub fn remove_worktree(name: &str, force: bool) -> Result<Output, CustomError> {
let mut args = vec!["worktree", "remove", name];
if force {
args.push("--force");
}
git(&args)
}
pub fn delete_branch(branch: &str, force: bool) -> Result<Output, CustomError> {
let mut args = vec!["branch", "-D", branch];
if !force {
args = vec!["branch", "-d", branch];
}
git(&args)
}
fn git(args: &[&str]) -> Result<Output, CustomError> {
let output = Command::new("git")
.args(args)
.output()?;
match output.status.success() {
true => Ok(output),
false => Err(CustomError::ProcessFailed(output.status.code(), "git".to_string(), std::str::from_utf8(&output.stdout).map(|str| str.to_string())?, std::str::from_utf8(&output.stderr).map(|str| str.to_string())?))
}
}