use {
super::TreeGitStatus,
crate::{
git,
task_sync::{Computation, ComputationResult, Dam},
},
crossbeam::channel::bounded,
ahash::AHashMap,
git2::Repository,
once_cell::sync::Lazy,
std::{
path::{Path, PathBuf},
sync::Mutex,
},
};
fn compute_tree_status(root_path: &Path) -> ComputationResult<TreeGitStatus> {
match Repository::open(root_path) {
Ok(git_repo) => {
let tree_git_status = time!(TreeGitStatus::from(&git_repo),);
match tree_git_status {
Some(gs) => ComputationResult::Done(gs),
None => ComputationResult::None,
}
}
Err(e) => {
debug!("failed to discover repo: {:?}", e);
ComputationResult::None
}
}
}
static TS_CACHE_MX: Lazy<Mutex<AHashMap<PathBuf, Computation<TreeGitStatus>>>> = Lazy::new(|| {
Mutex::new(AHashMap::default())
});
pub fn get_tree_status(root_path: &Path, dam: &mut Dam) -> ComputationResult<TreeGitStatus> {
match git::closest_repo_dir(root_path) {
None => ComputationResult::None,
Some(repo_path) => {
let comp = TS_CACHE_MX
.lock()
.unwrap()
.get(&repo_path)
.map(|c| (*c).clone());
match comp {
Some(Computation::Finished(comp_res)) => {
comp_res
}
Some(Computation::InProgress(comp_receiver)) => {
debug!("start select on in progress computation");
dam.select(comp_receiver)
}
None => {
let (s, r) = bounded(1);
TS_CACHE_MX
.lock()
.unwrap()
.insert(repo_path.clone(), Computation::InProgress(r));
dam.try_compute(move || {
let comp_res = compute_tree_status(&repo_path);
TS_CACHE_MX
.lock()
.unwrap()
.insert(repo_path.clone(), Computation::Finished(comp_res.clone()));
if let Err(e) = s.send(comp_res.clone()) {
debug!("error while sending comp result: {:?}", e);
}
comp_res
})
}
}
}
}
}
pub fn clear_status_computer_cache() {
let mut ts_cache = TS_CACHE_MX.lock().unwrap();
ts_cache.clear();
}