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