use std::{cell::RefCell, sync::Arc};
use anyhow::Context;
use askama::Template;
use axum::{
response::{IntoResponse, Response},
Extension,
};
use itertools::{Either, Itertools};
use super::filters;
use crate::{
database::schema::repository::{Repository, YokedRepository},
into_response,
};
#[derive(Template)]
#[template(path = "index.html")]
pub struct View<
'a,
Group: Iterator<Item = (&'a String, &'a YokedRepository)>,
GroupIter: Iterator<Item = (&'a str, Group)>,
> {
pub repositories: RefCell<Either<GroupIter, std::iter::Empty<(&'a str, Group)>>>,
}
impl<'a, Group, GroupIter> View<'a, Group, GroupIter>
where
Group: Iterator<Item = (&'a String, &'a YokedRepository)>,
GroupIter: Iterator<Item = (&'a str, Group)>,
{
fn take_iter(&self) -> Either<GroupIter, std::iter::Empty<(&'a str, Group)>> {
self.repositories.replace(Either::Right(std::iter::empty()))
}
}
pub async fn handle(
Extension(db): Extension<Arc<rocksdb::DB>>,
) -> Result<Response, super::repo::Error> {
let fetched = tokio::task::spawn_blocking(move || Repository::fetch_all(&db))
.await
.context("Failed to join Tokio task")??;
let repositories = fetched
.iter()
.group_by(|(k, _)| memchr::memrchr(b'/', k.as_bytes()).map_or("", |idx| &k[..idx]));
Ok(into_response(View {
repositories: Either::Left(repositories.into_iter()).into(),
})
.into_response())
}