2023-06-25 15:51:05 +00:00
|
|
|
use crate::error::unexpected::Mappable;
|
|
|
|
use crate::origin::{self, store};
|
|
|
|
use std::sync;
|
|
|
|
|
2023-06-29 14:54:55 +00:00
|
|
|
pub struct Store<F, S>
|
2023-06-25 15:51:05 +00:00
|
|
|
where
|
2023-06-29 14:54:55 +00:00
|
|
|
S: store::Store + 'static,
|
2023-06-25 15:51:05 +00:00
|
|
|
F: Fn(&origin::Descr) -> Option<S> + Sync + Send,
|
|
|
|
{
|
|
|
|
mapping_fn: F,
|
|
|
|
stores: Vec<S>,
|
|
|
|
}
|
|
|
|
|
2023-06-29 14:54:55 +00:00
|
|
|
impl<F, S> Store<F, S>
|
2023-06-25 15:51:05 +00:00
|
|
|
where
|
|
|
|
S: store::Store + 'static,
|
2023-06-29 14:54:55 +00:00
|
|
|
F: Fn(&origin::Descr) -> Option<S> + Sync + Send,
|
2023-06-25 15:51:05 +00:00
|
|
|
{
|
2023-06-29 14:54:55 +00:00
|
|
|
pub fn new(mapping_fn: F, stores: Vec<S>) -> Store<F, S> {
|
|
|
|
Store { mapping_fn, stores }
|
|
|
|
}
|
2023-06-25 15:51:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<F, S> store::Store for Store<F, S>
|
|
|
|
where
|
2023-06-29 14:54:55 +00:00
|
|
|
S: store::Store + 'static,
|
2023-06-25 15:51:05 +00:00
|
|
|
F: Fn(&origin::Descr) -> Option<S> + Sync + Send,
|
|
|
|
{
|
2023-07-04 17:33:03 +00:00
|
|
|
fn sync(&self, descr: &origin::Descr) -> Result<(), store::SyncError> {
|
|
|
|
(self.mapping_fn)(descr)
|
2023-07-03 12:30:41 +00:00
|
|
|
.or_unexpected_while(format!("mapping {:?} to store", &descr))?
|
2023-07-04 17:33:03 +00:00
|
|
|
.sync(descr)
|
2023-06-25 15:51:05 +00:00
|
|
|
}
|
|
|
|
|
2023-07-04 17:33:03 +00:00
|
|
|
fn get(&self, descr: &origin::Descr) -> Result<sync::Arc<dyn origin::Origin>, store::GetError> {
|
|
|
|
(self.mapping_fn)(descr)
|
2023-07-03 12:30:41 +00:00
|
|
|
.or_unexpected_while(format!("mapping {:?} to store", &descr))?
|
2023-06-25 15:51:05 +00:00
|
|
|
.get(descr)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_descrs(&self) -> Result<Vec<origin::Descr>, store::AllDescrsError> {
|
|
|
|
let mut res = Vec::<origin::Descr>::new();
|
|
|
|
|
|
|
|
for store in self.stores.iter() {
|
|
|
|
store.all_descrs()?.into_iter().collect_into(&mut res);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use crate::origin::{self, store};
|
2023-07-03 12:30:41 +00:00
|
|
|
use std::sync;
|
|
|
|
|
|
|
|
struct Harness {
|
|
|
|
descr_a: origin::Descr,
|
|
|
|
descr_b: origin::Descr,
|
|
|
|
descr_unknown: origin::Descr,
|
|
|
|
store_a: sync::Arc<sync::Mutex<store::MockStore>>,
|
|
|
|
store_b: sync::Arc<sync::Mutex<store::MockStore>>,
|
|
|
|
store: Box<dyn store::Store>,
|
|
|
|
}
|
2023-06-25 15:51:05 +00:00
|
|
|
|
2023-07-03 12:30:41 +00:00
|
|
|
impl Harness {
|
|
|
|
fn new() -> Harness {
|
|
|
|
let descr_a = origin::Descr::Git {
|
|
|
|
url: "A".to_string(),
|
|
|
|
branch_name: "A".to_string(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let descr_b = origin::Descr::Git {
|
|
|
|
url: "B".to_string(),
|
|
|
|
branch_name: "B".to_string(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let store_a = store::new_mock();
|
|
|
|
let store_b = store::new_mock();
|
|
|
|
|
|
|
|
Harness {
|
|
|
|
descr_a: descr_a.clone(),
|
|
|
|
descr_b: descr_b.clone(),
|
|
|
|
descr_unknown: origin::Descr::Git {
|
|
|
|
url: "X".to_string(),
|
|
|
|
branch_name: "X".to_string(),
|
2023-06-25 15:51:05 +00:00
|
|
|
},
|
2023-07-03 12:30:41 +00:00
|
|
|
store_a: store_a.clone(),
|
|
|
|
store_b: store_b.clone(),
|
|
|
|
store: Box::from(super::Store::new(
|
|
|
|
{
|
|
|
|
let store_a = store_a.clone();
|
|
|
|
let store_b = store_b.clone();
|
|
|
|
move |descr| match descr {
|
|
|
|
&origin::Descr::Git { ref url, .. } if url == "A" => {
|
|
|
|
Some(store_a.clone())
|
|
|
|
}
|
|
|
|
&origin::Descr::Git { ref url, .. } if url == "B" => {
|
|
|
|
Some(store_b.clone())
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
vec![store_a.clone(), store_b.clone()],
|
|
|
|
)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sync() {
|
|
|
|
let h = Harness::new();
|
|
|
|
|
2023-07-04 17:33:03 +00:00
|
|
|
{
|
|
|
|
let descr_a = h.descr_a.clone();
|
|
|
|
h.store_a
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.expect_sync()
|
|
|
|
.withf(move |descr: &origin::Descr| descr == &descr_a)
|
|
|
|
.times(1)
|
|
|
|
.return_const(Ok::<(), store::SyncError>(()));
|
|
|
|
}
|
2023-06-25 15:51:05 +00:00
|
|
|
|
2023-07-04 17:33:03 +00:00
|
|
|
assert_eq!(Ok(()), h.store.sync(&h.descr_a));
|
|
|
|
|
|
|
|
{
|
|
|
|
let descr_b = h.descr_b.clone();
|
|
|
|
h.store_b
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.expect_sync()
|
|
|
|
.withf(move |descr: &origin::Descr| descr == &descr_b)
|
|
|
|
.times(1)
|
|
|
|
.return_const(Ok::<(), store::SyncError>(()));
|
|
|
|
}
|
2023-06-25 15:51:05 +00:00
|
|
|
|
2023-07-04 17:33:03 +00:00
|
|
|
assert_eq!(Ok(()), h.store.sync(&h.descr_b));
|
2023-07-03 12:30:41 +00:00
|
|
|
|
2023-07-04 17:33:03 +00:00
|
|
|
assert!(h.store.sync(&h.descr_unknown).is_err());
|
2023-07-03 12:30:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn all_descrs() {
|
|
|
|
let h = Harness::new();
|
|
|
|
|
|
|
|
h.store_a
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.expect_all_descrs()
|
|
|
|
.times(1)
|
|
|
|
.return_const(Ok::<Vec<origin::Descr>, store::AllDescrsError>(vec![h
|
|
|
|
.descr_a
|
|
|
|
.clone()]));
|
|
|
|
|
|
|
|
h.store_b
|
|
|
|
.lock()
|
|
|
|
.unwrap()
|
|
|
|
.expect_all_descrs()
|
|
|
|
.times(1)
|
|
|
|
.return_const(Ok::<Vec<origin::Descr>, store::AllDescrsError>(vec![h
|
|
|
|
.descr_b
|
|
|
|
.clone()]));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
Ok(vec![h.descr_a.clone(), h.descr_b.clone()]),
|
|
|
|
h.store.all_descrs(),
|
|
|
|
)
|
2023-06-25 15:51:05 +00:00
|
|
|
}
|
|
|
|
}
|