raw
1use axum::{
2 extract::Path,
3 http::StatusCode,
4 response::{IntoResponse as _, Response},
5};
6use git2::Commit;
7
8use crate::utils::{
9 Error, Result, error::Context as _, extractor::repo_name_checks, filters, git::Repository,
10 response::Xml, spawn_blocking,
11};
12
13#[derive(askama::Template)]
14#[template(path = "log.xml")]
15struct RepoLogFeedTemplate<'a> {
16 repo: &'a Repository,
17 commits: Vec<Commit<'a>>,
18 branch: String,
19 base_url: &'a str,
20}
21
22#[tracing::instrument(skip_all)]
23pub async fn get_1(Path(repo_name): Path<String>) -> Response {
24 spawn_blocking(move || inner(&repo_name, None).into_response()).await
25}
26
27#[tracing::instrument(skip_all)]
28pub async fn get_2(Path((repo_name, r#ref)): Path<(String, String)>) -> Response {
29 spawn_blocking(move || inner(&repo_name, Some(&r#ref)).into_response()).await
30}
31
32fn inner(repo_name: &str, r#ref: Option<&str>) -> Result {
33 repo_name_checks(repo_name)?;
34
35 let Some(repo) = Repository::open(repo_name).context("opening repository")? else {
36 return Err(Error::new(StatusCode::NOT_FOUND, "repo does not exist"));
37 };
38
39 if repo.is_empty()? {
40 return Err(Error::new(
42 StatusCode::SERVICE_UNAVAILABLE,
43 "Cannot show feed because there are no commits.",
44 ));
45 }
46
47 let r = r#ref.unwrap_or("HEAD");
48
49 let Some(commits) = repo.commits(r, crate::config().log_per_page)? else {
50 return Err(Error::new(StatusCode::NOT_FOUND, "crepo does not exist"));
51 };
52
53 let branch = repo.ref_or_head_shorthand(r#ref)?;
54
55 Ok(Xml(RepoLogFeedTemplate {
56 repo: &repo,
57 commits,
58 branch,
59 base_url: &format!("/{repo_name}"),
60 })
61 .into_response())
62}
63