1use std::{collections::BTreeMap, sync::Arc};
2
3use crate::{
4 into_response,
5 methods::{
6 filters,
7 repo::{Refs, Repository, Result},
8 },
9};
10use anyhow::Context;
11use askama::Template;
12use axum::{Extension, response::IntoResponse};
13use rkyv::string::ArchivedString;
14use yoke::Yoke;
15
16#[derive(Template)]
17#[template(path = "repo/refs.html")]
18pub struct View {
19 repo: Repository,
20 refs: Refs,
21 branch: Option<Arc<str>>,
22}
23
24pub async fn handle(
25 Extension(repo): Extension<Repository>,
26 Extension(db): Extension<Arc<rocksdb::DB>>,
27) -> Result<impl IntoResponse> {
28 tokio::task::spawn_blocking(move || {
29 let repository = crate::database::schema::repository::Repository::open(&db, &*repo)?
30 .context("Repository does not exist")?;
31 let repository = repository.get();
32
33 let heads_db = repository.heads(&db)?;
34 let heads_db = heads_db.as_ref().map(Yoke::get);
35
36 let mut heads = BTreeMap::new();
37 if let Some(archived_heads) = heads_db {
38 for head in archived_heads
39 .0
40 .as_slice()
41 .iter()
42 .map(ArchivedString::as_str)
43 {
44 let commit_tree = repository.commit_tree(db.clone(), head);
45 let name = head.strip_prefix("refs/heads/");
46
47 if let (Some(name), Some(commit)) = (name, commit_tree.fetch_latest_one()?) {
48 heads.insert(name.to_string(), commit);
49 }
50 }
51 }
52
53 let tags = repository.tag_tree(db).fetch_all()?;
54
55 Ok(into_response(View {
56 repo,
57 refs: Refs { heads, tags },
58 branch: None,
59 }))
60 })
61 .await
62 .context("Failed to attach to tokio task")?
63}