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