//! `/{repo}/refs` — branches and tags. use askama::Template; use axum::http::StatusCode; use axum::response::Response; use super::repo::{Active, Crumb, Ctx, RepoNav, set_cache_headers}; use super::{Layout, render}; use crate::git::refs::RefEntry; use crate::render::time; pub struct RefRow { pub name: String, pub url: String, pub subject: String, pub age: String, pub iso: String, pub is_default: bool, } #[derive(Template)] #[template(path = "refs.html")] pub struct RefsPage { pub layout: Layout, pub nav: RepoNav, pub crumbs: Vec, pub here: Option, pub branches: Vec, pub tags: Vec, } pub fn page(ctx: &Ctx) -> Response { let etag = ctx.etag("refs"); if let Some(res) = ctx.not_modified(&etag, false) { return res; } let refs = match ctx.refs() { Ok(refs) => refs, Err(e) => return ctx.internal_error(e), }; let now = time::now(); let default = ctx.repo.meta.default_branch.as_deref(); let row = |r: &RefEntry| RefRow { name: r.name.clone(), url: ctx.url("tree", &r.name, b""), subject: r .tag_subject .clone() .unwrap_or_else(|| r.info.subject.clone()), age: time::relative(r.info.committer_time, now), iso: time::iso(r.info.committer_time), is_default: false, }; let mut branches: Vec = refs.branches.iter().map(row).collect(); // The default branch leads the list. if let Some(i) = branches .iter() .position(|b| Some(b.name.as_str()) == default) { let mut b = branches.remove(i); b.is_default = true; branches.insert(0, b); } let crumbs = vec![Crumb { name: ctx.repo.name.clone(), url: ctx.repo_url(), }]; let page = RefsPage { layout: Layout::new( ctx.state, ctx.config, Some(&format!("Refs · {}", ctx.repo.name)), ), nav: ctx.nav(Active::Refs, None, |_| String::new()), crumbs, here: Some("Refs".into()), branches, tags: refs.tags.iter().map(row).collect(), }; let mut res = render(StatusCode::OK, &page); set_cache_headers(&mut res, &etag, false); res }