raw
1use axum::{
2 extract::Path,
3 http::StatusCode,
4 response::{IntoResponse, Response},
5};
6use git2::Tag;
7
8use crate::utils::{
9 Error, Result,
10 error::Context as _,
11 extractor::repo_name_checks,
12 filters,
13 git::Repository,
14 response::{Html, Redirect},
15 spawn_blocking,
16};
17
18#[derive(askama::Template)]
19#[template(path = "tag.html")]
20struct Template<'a> {
21 repo: &'a Repository,
22 tag: Tag<'a>,
23}
24
25#[tracing::instrument(skip_all)]
26pub async fn get(Path((repo_name, tag)): Path<(String, String)>) -> Response {
27 spawn_blocking(move || inner(&repo_name, &tag).into_response()).await
28}
29
30#[tracing::instrument(skip_all)]
31fn inner(repo_name: &str, tag: &str) -> Result {
32 repo_name_checks(repo_name)?;
33
34 let Some(repo) = Repository::open(repo_name).context("opening repository")? else {
35 return Err(Error::new(StatusCode::NOT_FOUND, "repo does not exist"));
36 };
37
38 let Ok(repo_tag) = repo.tag(tag) else {
39 return Ok(Redirect::permanent(&format!("/{repo_name}/commit/{tag}"))
40 .unwrap_or(Redirect::PERMANENT_ROOT)
41 .into_response());
42 };
43
44 Ok(Html(Template {
45 repo: &repo,
46 tag: repo_tag,
47 })
48 .into_response())
49}
50