use std::path::PathBuf;
use super::{Repo, RepoError};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct RepoStatus {
pub staged: Vec<PathBuf>,
pub unstaged: Vec<PathBuf>,
pub untracked: Vec<PathBuf>,
}
impl Repo {
pub async fn status(&self) -> Result<RepoStatus, RepoError> {
let inner = self.thread_safe();
tokio::task::spawn_blocking(move || compute_status(&inner)).await.map_err(|join_err| {
RepoError::StatusFailed { cause: format!("spawn_blocking join error: {join_err}") }
})?
}
}
fn compute_status(inner: &gix::ThreadSafeRepository) -> Result<RepoStatus, RepoError> {
let repo = inner.to_thread_local();
let platform = repo
.status(gix::progress::Discard)
.map_err(|e| RepoError::StatusFailed { cause: e.to_string() })?
.untracked_files(gix::status::UntrackedFiles::Files);
let staged: Vec<PathBuf> = Vec::new();
let mut unstaged: Vec<PathBuf> = Vec::new();
let mut untracked: Vec<PathBuf> = Vec::new();
let iter = platform
.into_iter(std::iter::empty::<gix::bstr::BString>())
.map_err(|e| RepoError::StatusFailed { cause: e.to_string() })?;
for item in iter {
let item = item.map_err(|e| RepoError::StatusFailed { cause: e.to_string() })?;
match item {
gix::status::Item::IndexWorktree(iw) => match iw {
gix::status::index_worktree::Item::Modification { rela_path, .. } => {
unstaged.push(gix::path::from_bstring(rela_path));
}
gix::status::index_worktree::Item::Rewrite { dirwalk_entry, .. } => {
unstaged.push(gix::path::from_bstring(dirwalk_entry.rela_path));
}
gix::status::index_worktree::Item::DirectoryContents { entry, .. } => {
if matches!(entry.status, gix::dir::entry::Status::Untracked) {
untracked.push(gix::path::from_bstring(entry.rela_path));
}
}
},
gix::status::Item::TreeIndex(_) => {
}
}
}
Ok(RepoStatus { staged, unstaged, untracked })
}