use crate::Result;
use git2::Repository;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BranchInfo {
pub name: String,
pub is_current: bool,
pub upstream: Option<String>,
pub commit_id: Option<String>,
}
impl BranchInfo {
pub fn current(repo: &Repository) -> Result<Option<Self>> {
let head = match repo.head() {
Ok(h) => h,
Err(_) => return Ok(None),
};
if head.is_branch() {
let name = head
.name()
.map(|n| n.strip_prefix("refs/heads/").unwrap_or(n).to_string())
.unwrap_or_else(|| "HEAD".to_string());
let commit_id = head.peel_to_commit().ok().map(|c| c.id().to_string());
return Ok(Some(Self {
name,
is_current: true,
upstream: None,
commit_id,
}));
}
Ok(None)
}
pub fn list(repo: &Repository) -> Result<Vec<Self>> {
let mut branches = Vec::new();
let current = Self::current(repo)?;
let current_name = current.as_ref().map(|b| b.name.clone());
let branch_names = repo.branches(None)?;
for branch in branch_names.flatten() {
if let Ok(Some(name)) = branch.0.name() {
let name = name.strip_prefix("refs/heads/").unwrap_or(name).to_string();
let is_current = current_name.as_ref() == Some(&name);
let commit_id = branch
.0
.get()
.peel_to_commit()
.ok()
.map(|c| c.id().to_string());
branches.push(Self {
name,
is_current,
upstream: None,
commit_id,
});
}
}
Ok(branches)
}
}