1use std::{collections::BTreeMap, sync::Arc};
2
3use anyhow::Context;
4use askama::Template;
5use axum::{response::IntoResponse, Extension};
6
7use crate::{
8 database::schema::{commit::YokedCommit, repository::YokedRepository},
9 into_response,
10 methods::{
11 filters,
12 repo::{Refs, Repository, Result, DEFAULT_BRANCHES},
13 },
14};
15
16#[derive(Template)]
17#[template(path = "repo/summary.html")]
18pub struct View {
19 repo: Repository,
20 refs: Refs,
21 commit_list: Vec<YokedCommit>,
22 branch: Option<Arc<str>>,
23}
24
25pub async fn handle(
26 Extension(repo): Extension<Repository>,
27 Extension(db): Extension<Arc<rocksdb::DB>>,
28) -> Result<impl IntoResponse> {
29 tokio::task::spawn_blocking(move || {
30 let repository = crate::database::schema::repository::Repository::open(&db, &*repo)?
31 .context("Repository does not exist")?;
32 let commits = get_default_branch_commits(&repository, &db)?;
33
34 let mut heads = BTreeMap::new();
35 for head in repository.get().heads(&db)?.get() {
36 let commit_tree = repository.get().commit_tree(db.clone(), head);
37 let name = head.strip_prefix("refs/heads/");
38
39 if let (Some(name), Some(commit)) = (name, commit_tree.fetch_latest_one()?) {
40 heads.insert(name.to_string(), commit);
41 }
42 }
43
44 let tags = repository.get().tag_tree(db).fetch_all()?;
45
46 Ok(into_response(View {
47 repo,
48 refs: Refs { heads, tags },
49 commit_list: commits,
50 branch: None,
51 }))
52 })
53 .await
54 .context("Failed to attach to tokio task")?
55}
56
57pub fn get_default_branch_commits(
58 repository: &YokedRepository,
59 database: &Arc<rocksdb::DB>,
60) -> Result<Vec<YokedCommit>> {
61 for branch in repository
62 .get()
63 .default_branch
64 .as_deref()
65 .into_iter()
66 .chain(DEFAULT_BRANCHES.into_iter())
67 {
68 let commit_tree = repository.get().commit_tree(database.clone(), branch);
69 let commits = commit_tree.fetch_latest(11, 0)?;
70
71 if !commits.is_empty() {
72 return Ok(commits);
73 }
74 }
75
76 Ok(vec![])
77}