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::error::Result;
15use crate::git;
16use crate::routes::{AppState, RepoName};
17
18#[derive(Deserialize)]
19pub(super) struct TagPath {
20    tag: String,
21}
22
23/// Template context for the tag list page.
24#[derive(Template, WebTemplate)]
25#[template(path = "tag_list.html")]
26struct TagList {
27    repo: String,
28    tags: Vec<git::TagInfo>,
29}
30
31/// Template context for the tag detail page.
32#[derive(Template, WebTemplate)]
33#[template(path = "tag_detail.html")]
34struct TagDetail {
35    repo: String,
36    tag: String,
37    tagger: Option<String>,
38    tag_date: Option<String>,
39    message: Option<String>,
40    commit_sha: String,
41    commit_author: String,
42    commit_date: String,
43}
44
45/// Renders the full list of tags for a repository, sorted newest first.
46pub async fn list(
47    State(state): State<AppState>,
48    RepoName(repo): RepoName,
49) -> Result<impl IntoResponse> {
50    let git_repo = git::open_repo(&state.root, &repo)?;
51    let tags = git::load_tags(&git_repo);
52    Ok(TagList { repo, tags })
53}
54
55/// Renders the detail page for a single tag.
56pub async fn detail(
57    State(state): State<AppState>,
58    RepoName(repo): RepoName,
59    Path(params): Path<TagPath>,
60) -> Result<impl IntoResponse> {
61    let git_repo = git::open_repo(&state.root, &repo)?;
62    let (annotation, commit) = git::load_tag(&git_repo, &params.tag)?;
63
64    Ok(TagDetail {
65        repo,
66        tag: params.tag,
67        tagger: annotation.tagger,
68        tag_date: annotation.date,
69        message: annotation.message,
70        commit_sha: commit.sha,
71        commit_author: commit.author,
72        commit_date: commit.date,
73    })
74}