use std::collections::HashMap;
use radicle::git::Oid;
use radicle::git::fmt::{Component, Qualified, RefString};
use radicle::prelude::PublicKey;
use super::refs::{Applied, RefUpdate, Update};
/// An in-memory reference store.
///
/// It provides the same functionality as the [`super::Refdb`], but is
/// used to temporarily store reference names and objects.
#[derive(Clone, Debug, Default)]
pub struct Refdb(HashMap<Qualified<'static>, Oid>);
impl Refdb {
pub fn refname_to_id<'a, N>(&self, refname: N) -> Option<Oid>
where
N: Into<Qualified<'a>>,
{
let name = refname.into();
self.0.get(&name).copied()
}
pub fn references_of<'a>(
&'a self,
remote: &'a PublicKey,
) -> impl Iterator<Item = (RefString, Oid)> + 'a {
let remote = Component::from(remote);
self.0.iter().filter_map(move |(refname, oid)| {
let ns = refname.to_namespaced()?;
(ns.namespace() == remote).then(|| (ns.strip_namespace().to_ref_string(), *oid))
})
}
pub fn update<'a, I>(&mut self, updates: I) -> Applied<'a>
where
I: IntoIterator<Item = Update<'a>>,
{
updates
.into_iter()
.fold(Applied::default(), |mut ap, update| match update {
Update::Direct { name, target, .. } => {
let name = name.into_qualified().into_owned();
let prev = self
.0
.insert(name.clone(), target)
.unwrap_or(radicle::git::Oid::ZERO_SHA1);
ap.updated.push(RefUpdate::Updated {
name: name.to_ref_string(),
old: prev,
new: target,
});
ap
}
Update::Prune { name, .. } => {
let name = name.into_qualified().into_owned();
if let Some((name, prev)) = self.0.remove_entry(&name) {
ap.updated.push(RefUpdate::Deleted {
name: name.to_ref_string(),
oid: prev,
})
}
ap
}
})
}
#[allow(dead_code)]
pub(crate) fn inspect(&self) {
if self.0.is_empty() {
println!("Refdb is empty!");
} else {
for (name, oid) in self.0.iter() {
println!("{name} -> {oid}");
}
}
}
}