mygit

[UNMAINTAINED] A cgit/webgit alternative, written in Rust
Log | Files | Refs | README | LICENSE

commit 58c7e1858c8472dc743051a9a42508e4a4175b05
parent cf81aa091fd37dddff47eb276c3b65b6d373735a
Author: Johann150 <johann@qwertqwefsday.eu>
Date:   Fri, 16 Apr 2021 19:32:20 +0200

add RSS feed for tags

This feed does not include branches as I thought this does not make much sense.

Diffstat:
Msrc/main.rs | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/refs.xml | 26++++++++++++++++++++++++++
2 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -779,6 +779,76 @@ async fn repo_log_feed(req: Request<()>) -> tide::Result { Ok(response) } +#[derive(Template)] +#[template(path = "refs.xml")] +struct RepoRefFeedTemplate<'a> { + repo: &'a Repository, + tags: Vec<(String, Signature<'static>, String)>, + base_url: &'a str, +} + +async fn repo_refs_feed(req: Request<()>) -> tide::Result { + let repo = repo_from_request(&req.param("repo_name")?)?; + if repo.is_empty().unwrap() { + // show a server error + return Err(tide::Error::from_str( + 503, + "Cannot show feed because there is nothing here.", + )); + } + + let mut tags = Vec::new(); + repo.tag_foreach(|oid, name_bytes| { + let obj = repo.find_object(oid, None).unwrap(); + let (signature, message) = match obj.kind().unwrap() { + git2::ObjectType::Tag => { + let tag = obj.as_tag().unwrap(); + ( + tag.tagger() + .unwrap_or_else(|| obj.peel_to_commit().unwrap().committer().to_owned()) + .to_owned(), + tag.message().unwrap_or("").to_string(), + ) + } + git2::ObjectType::Commit => { + // lightweight tag, therefore no content + ( + obj.as_commit().unwrap().committer().to_owned(), + String::new(), + ) + } + _ => unreachable!("a tag was not a tag or lightweight tag"), + }; + tags.push(( + // remove prefix "ref/tags/" + String::from_utf8(name_bytes[10..].to_vec()).unwrap(), + signature, + message, + )); + true + }) + .unwrap(); + // sort so that newest tags are at the top + tags.sort_unstable_by(|(_, a, _), (_, b, _)| a.when().cmp(&b.when()).reverse()); + + let mut url = req.url().clone(); + { + let mut segments = url.path_segments_mut().unwrap(); + segments.pop(); // pop "feed.xml" + segments.pop(); // pop "log/" or ref + if req.param("ref").is_ok() { + segments.pop(); // the last pop was a ref, now pop "log/" + } + } + + let tmpl = RepoRefFeedTemplate { + repo: &repo, + tags, + base_url: url.as_str(), + }; + Ok(tmpl.into()) +} + mod filters { use super::*; @@ -893,6 +963,8 @@ async fn main() -> Result<(), std::io::Error> { // web pages app.at("/:repo_name/commit/:commit").get(repo_commit); app.at("/:repo_name/refs").get(repo_refs); + app.at("/:repo_name/refs/").get(repo_refs); + app.at("/:repo_name/refs/feed.xml").get(repo_refs_feed); app.at("/:repo_name/log").get(repo_log); app.at("/:repo_name/log/").get(repo_log); app.at("/:repo_name/log/:ref").get(repo_log); // ref is optional diff --git a/templates/refs.xml b/templates/refs.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0"> + <channel> + <title>{{repo|repo_name}} tags</title> + <link>{{base_url}}/refs#tags</link> + <description> + Tags of the repository {{repo|repo_name}}: + &lt;p&gt;{{repo|description}}&lt;/p&gt; + </description> + <ttl>30</ttl> + <generator>mygit</generator> + <lastBuildDate>{{repo|last_modified|format_datetime("%a, %e %b %Y %T %z")}}</lastBuildDate> + <managingEditor>{{repo|repo_owner}}</managingEditor> + <docs>https://www.rssboard.org/rss-specification</docs> + {% for (tag, signature, message) in tags %} + <item> + <title>{{tag}}</title> + <link>{{base_url}}/commit/{{tag}}</link> + <guid isPermaLink="true">{{base_url}}/commit/{{tag}}</guid> + <description>&lt;pre&gt;{{message}}&lt;/pre&gt;</description> + <author>{{signature.email().unwrap_or("")}}</author> + <pubDate>{{signature.when()|format_datetime("%a, %e %b %Y %T %z")}}</pubDate> + </item> + {% endfor %} + </channel> +</rss>