use std::collections::BTreeMap;
use either::Either;
use radicle::git::Oid;
use radicle::git::fmt::{Namespaced, Qualified};
use radicle::prelude::PublicKey;
pub use radicle::storage::RefUpdate;
#[derive(Debug, Default)]
pub struct Applied<'a> {
pub rejected: Vec<Update<'a>>,
pub updated: Vec<RefUpdate>,
}
impl Applied<'_> {
pub fn append(&mut self, other: &mut Self) {
self.rejected.append(&mut other.rejected);
self.updated.append(&mut other.updated);
}
}
#[derive(Clone, Default, Debug)]
pub struct Updates<'a> {
pub tips: BTreeMap<PublicKey, Vec<Update<'a>>>,
}
impl<'a> Updates<'a> {
pub fn build(updates: impl IntoIterator<Item = (PublicKey, Update<'a>)>) -> Self {
let tips = updates.into_iter().fold(
BTreeMap::<_, Vec<Update<'a>>>::new(),
|mut tips, (remote, up)| {
tips.entry(remote)
.and_modify(|ups| ups.push(up.clone()))
.or_insert(vec![up]);
tips
},
);
Self { tips }
}
pub fn add(&mut self, remote: PublicKey, up: Update<'a>) {
self.tips
.entry(remote)
.and_modify(|ups| ups.push(up.clone()))
.or_insert(vec![up]);
}
pub fn append(&mut self, remote: PublicKey, mut new: Vec<Update<'a>>) {
self.tips
.entry(remote)
.and_modify(|ups| ups.append(&mut new))
.or_insert(new);
}
}
#[derive(Clone, Copy, Debug)]
pub enum Policy {
Abort,
Reject,
Allow,
}
#[derive(Clone, Debug)]
pub enum Update<'a> {
Direct {
name: Namespaced<'a>,
target: Oid,
no_ff: Policy,
},
Prune {
name: Namespaced<'a>,
prev: Either<Oid, Qualified<'a>>,
},
}
impl<'a> Update<'a> {
pub fn refname(&self) -> &Namespaced<'a> {
match self {
Update::Direct { name, .. } => name,
Update::Prune { name, .. } => name,
}
}
pub fn into_owned<'b>(self) -> Update<'b> {
match self {
Self::Direct {
name,
target,
no_ff,
} => Update::Direct {
name: name.into_owned(),
target,
no_ff,
},
Self::Prune { name, prev } => Update::Prune {
name: name.into_owned(),
prev: prev.map_right(|q| q.into_owned()),
},
}
}
}