Parent [>]
1//! Route handlers for tag pages.
2//!
3//! Covers two routes: the tag list (`/{repo}/tags`) and the tag detail page
4//! (`/{repo}/tags/{*tag}`).  The detail handler peels the tag ref to its
5//! commit and presents a release-oriented view with the annotation message,
6//! commit info, and archive download links.
7
8use askama::Template;
9use askama_web::WebTemplate;
10use axum::extract::{Path, State};
11use axum::response::IntoResponse;
12use serde::Deserialize;
13
14use crate::config::SiteConfig;
15use crate::error::Result;
16use crate::filters;
17use crate::git;
18use crate::routes::{AppState, RepoName};
19
20#[derive(Deserialize)]
21pub(super) struct TagPath {
22    tag: String,
23}
24
25/// Template context for the tag list page.
26#[derive(Template, WebTemplate)]
27#[template(path = "tag_list.html")]
28struct TagList {
29    repo: String,
30    tags: Vec<git::TagInfo>,
31    site: std::sync::Arc<SiteConfig>,
32}
33
34/// Template context for the tag detail page.
35#[derive(Template, WebTemplate)]
36#[template(path = "tag_detail.html")]
37struct TagDetail {
38    repo: String,
39    tag: String,
40    tagger: Option<String>,
41    tag_date: Option<String>,
42    message: Option<String>,
43    commit_sha: String,
44    commit_author: String,
45    commit_date: String,
46    site: std::sync::Arc<SiteConfig>,
47}
48
49/// Renders the full list of tags for a repository, sorted newest first.
50pub async fn list(
51    State(state): State<AppState>,
52    RepoName(repo): RepoName,
53) -> Result<impl IntoResponse> {
54    let git_repo = git::open_repo(&state.root, &repo)?;
55    let tags = git::load_tags(&git_repo);
56    Ok(TagList {
57        repo,
58        tags,
59        site: state.site,
60    })
61}
62
63/// Renders the detail page for a single tag.
64pub async fn detail(
65    State(state): State<AppState>,
66    RepoName(repo): RepoName,
67    Path(params): Path<TagPath>,
68) -> Result<impl IntoResponse> {
69    let git_repo = git::open_repo(&state.root, &repo)?;
70    let (annotation, commit) = git::load_tag(&git_repo, &params.tag)?;
71
72    Ok(TagDetail {
73        repo,
74        tag: params.tag,
75        tagger: annotation.tagger,
76        tag_date: annotation.date,
77        message: annotation.message,
78        commit_sha: commit.sha,
79        commit_author: commit.author,
80        commit_date: commit.date,
81        site: state.site,
82    })
83}