use git2::{BranchType, Repository};
use crate::stack::{current_stack, StackModel};
use crate::worktree::{current_worktree, find_worktree, find_worktree_by_branch};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Resolution {
Navigate,
Checkout { host: String },
Materialize,
DeletedNode { branch: String },
NotFound,
}
pub fn resolve_action(repo: &Repository, name: &str, model: StackModel) -> Resolution {
if find_worktree_by_branch(repo, name).is_ok() {
return Resolution::Navigate;
}
if model == StackModel::None {
return if branch_exists(repo, name) {
Resolution::Materialize
} else {
Resolution::NotFound
};
}
let t_stack = current_stack(repo, name, model).ok().flatten();
if let (Ok(cur), Some(ts)) = (current_worktree(repo), &t_stack) {
if let Ok(Some(b)) = cur.branch() {
if ts.diffs.contains(&b) {
if let Some(n) = cur.name() {
return Resolution::Checkout {
host: n.to_string(),
};
}
}
}
}
if let Some(ts) = &t_stack {
let mut visited = std::collections::HashSet::new();
let mut node = name.to_string();
while let Some(parent) = ts.parents.get(&node) {
if *parent == ts.trunk || !visited.insert(parent.clone()) {
break; }
if let Ok(wt) = find_worktree(repo, parent) {
if let Some(n) = wt.name() {
return Resolution::Checkout {
host: n.to_string(),
};
}
}
node = parent.clone();
}
}
if branch_exists(repo, name) {
return Resolution::Materialize;
}
if t_stack.is_some() {
return Resolution::DeletedNode {
branch: name.to_string(),
};
}
Resolution::NotFound
}
pub fn branch_exists(repo: &Repository, name: &str) -> bool {
if repo.find_branch(name, BranchType::Local).is_ok() {
return true;
}
if let Ok(branches) = repo.branches(Some(BranchType::Remote)) {
for branch in branches.flatten() {
if let Ok(Some(full_name)) = branch.0.name() {
if let Some((_, branch_name)) = full_name.split_once('/') {
if branch_name == name {
return true;
}
}
}
}
}
false
}