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