use std::{path, rc};
#[derive(Clone)]
pub struct GitManager {
git_repo: rc::Rc<git2::Repository>,
}
impl GitManager {
pub fn new(vault_path: path::PathBuf) -> Option<Self> {
git2::Repository::discover(vault_path)
.map(|git_repo| Self {
git_repo: rc::Rc::new(git_repo),
})
.ok()
}
pub fn calculate_ahead_behind(&self) -> Option<(usize, usize)> {
let head = self.git_repo.head().ok()?;
let head_id = head.target()?;
let branch = self
.git_repo
.find_branch(head.shorthand().unwrap(), git2::BranchType::Local)
.unwrap();
let upstream = branch.upstream().ok()?;
let upstream_id = upstream.get().target()?;
self.git_repo.graph_ahead_behind(head_id, upstream_id).ok()
}
pub fn changes(&self) -> (bool, bool) {
let mut status_options = git2::StatusOptions::new();
let statuses = self.git_repo.statuses(Some(
status_options
.include_untracked(true)
.recurse_untracked_dirs(true)
.include_ignored(false)
.exclude_submodules(true),
));
if statuses.is_err() {
return (false, false);
}
let statuses = statuses.unwrap();
(
statuses.iter().any(|entry| {
let status = entry.status();
status.is_wt_modified()
|| status.is_wt_deleted()
|| status.is_wt_new()
|| status.is_wt_typechange()
|| status.is_wt_renamed()
}),
statuses.iter().any(|entry| {
let status = entry.status();
status.is_index_modified()
|| status.is_index_deleted()
|| status.is_index_new()
|| status.is_index_typechange()
|| status.is_index_renamed()
}),
)
}
}