raw
1use axum::{
2 extract::{Path, State},
3 http::StatusCode,
4 response::{IntoResponse as _, Response},
5};
6
7use crate::{
8 BileState,
9 config::Config,
10 error::Context as _,
11 git::Repository,
12 http::{
13 extractor::RepoName,
14 response::{ErrorPage, Html, Result},
15 },
16 utils::filters,
17};
18
19#[derive(askama::Template)]
20#[template(path = "repo.html")]
21struct RepoHomeTemplate<'a> {
22 config: &'a Config,
23 repo: &'a Repository,
24 commits: Vec<git2::Commit<'a>>,
25 readme_text: String,
26}
27
28#[tracing::instrument(skip_all)]
29pub(crate) async fn get(state: State<BileState>, Path(repo_name): Path<RepoName>) -> Response {
30 state.spawn(move |state| inner(&state, &repo_name)).await
31}
32
33#[tracing::instrument(skip_all)]
34fn inner(state: &BileState, repo_name: &RepoName) -> Result<Response> {
35 let Some(repo) = Repository::open(&state.config, repo_name).context("opening repository")?
36 else {
37 return Ok(ErrorPage::new(&state.config)
38 .with_status(StatusCode::NOT_FOUND)
39 .into_response());
40 };
41
42 let readme_text = repo.readme(&state.syntax);
43
44 let r = "HEAD";
46 let Some(commits) = repo.commits(r, 3)? else {
47 return Ok(ErrorPage::new(&state.config)
48 .with_status(StatusCode::NOT_FOUND)
49 .into_response());
50 };
51
52 Ok(Html(RepoHomeTemplate {
53 config: &state.config,
54 repo: &repo,
55 commits,
56 readme_text,
57 })
58 .into_response())
59}
60