use crate::error::{Result, WorktreeError};
pub fn branch_has_gone_upstream(repo: &git2::Repository, name: &str) -> Result<bool> {
let branch = match repo.find_branch(name, git2::BranchType::Local) {
Ok(b) => b,
Err(_) => return Ok(false), };
let config = repo.config()?;
let remote_key = format!("branch.{}.remote", name);
match config.get_string(&remote_key) {
Ok(_) => {
match branch.upstream() {
Ok(_) => Ok(false), Err(_) => Ok(true), }
}
Err(_) => Ok(false), }
}
pub fn branch_is_merged_into(
repo: &git2::Repository,
name: &str,
target_branch: &str,
) -> Result<bool> {
if name == target_branch {
return Ok(false);
}
let branch = match repo.find_branch(name, git2::BranchType::Local) {
Ok(b) => b,
Err(_) => return Ok(false), };
let target = match repo.find_branch(target_branch, git2::BranchType::Local) {
Ok(b) => b,
Err(_) => return Ok(false), };
let branch_oid = branch
.get()
.target()
.ok_or(WorktreeError::NoCurrentBranchTarget)?;
let target_oid = target.get().target().ok_or(WorktreeError::NoBranchTarget)?;
if branch_oid == target_oid {
return Ok(true);
}
Ok(repo.graph_descendant_of(target_oid, branch_oid)?)
}
pub fn branch_tip_at_or_behind(repo: &git2::Repository, name: &str, oid: &str) -> Result<bool> {
let branch = match repo.find_branch(name, git2::BranchType::Local) {
Ok(b) => b,
Err(_) => return Ok(false), };
let tip_oid = match branch.get().target() {
Some(o) => o,
None => return Ok(false),
};
tip_at_or_behind(repo, tip_oid, oid)
}
pub fn tip_at_or_behind(repo: &git2::Repository, tip: git2::Oid, oid: &str) -> Result<bool> {
if tip.to_string() == oid {
return Ok(true);
}
let target_oid = match git2::Oid::from_str(oid) {
Ok(o) => o,
Err(_) => return Ok(false),
};
if repo.find_commit(target_oid).is_err() {
return Ok(false);
}
Ok(repo.graph_descendant_of(target_oid, tip)?)
}