mygit

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

commit 0f26c619b2da2e7276b4174773c0ae62c98f25ee
parent 0eac2b8c1193ec50a553dbb85b2ee4929bda2eb9
Author: Johann150 <johann@qwertqwefsday.eu>
Date:   Sun, 11 Apr 2021 01:22:41 +0200

add RSS feed for commits

Diffstat:
Msrc/main.rs | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atemplates/log.xml | 25+++++++++++++++++++++++++
2 files changed, 97 insertions(+), 0 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -717,6 +717,68 @@ async fn static_resource(req: Request<()>) -> tide::Result { } } +#[derive(Template)] +#[template(path = "log.xml")] +struct RepoLogFeedTemplate<'a> { + repo: &'a Repository, + commits: Vec<Commit<'a>>, + branch: &'a str, + base_url: &'a str, +} + +async fn repo_log_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 are no commits.", + )); + } + + let commits = if repo.is_shallow() { + tide::log::warn!("repository {:?} is only a shallow clone", repo.path()); + vec![repo.head()?.peel_to_commit().unwrap()] + } else { + let mut revwalk = repo.revwalk()?; + let r = req.param("ref").unwrap_or("HEAD"); + revwalk.push(repo.revparse_single(r)?.peel_to_commit()?.id())?; + + revwalk.set_sorting(git2::Sort::TIME).unwrap(); + revwalk + .filter_map(|oid| repo.find_commit(oid.unwrap()).ok()) // TODO error handling + .take(CONFIG.log_per_page) + .collect() + }; + + let head_branch = repo.head()?; + let branch = req + .param("ref") + .ok() + .or_else(|| head_branch.shorthand()) + .unwrap(); + + 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 = RepoLogFeedTemplate { + repo: &repo, + commits, + branch, + base_url: url.as_str(), + }; + let mut response: tide::Response = tmpl.into(); + response.set_content_type("application/rss+xml"); + Ok(response) +} + mod filters { use super::*; @@ -786,6 +848,14 @@ mod filters { .when()) } + pub fn repo_owner(repo: &Repository) -> askama::Result<String> { + Ok(repo + .config() + .unwrap() + .get_string("gitweb.owner") + .unwrap_or_default()) + } + pub fn signature_email_link(signature: &Signature) -> askama::Result<String> { Ok(if let Some(email) = signature.email() { format!( @@ -826,6 +896,8 @@ async fn main() -> Result<(), std::io::Error> { 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 + app.at("/:repo_name/log/feed.xml").get(repo_log_feed); + app.at("/:repo_name/log/:ref/feed.xml").get(repo_log_feed); // ref is optional app.at("/:repo_name/tree").get(repo_tree); app.at("/:repo_name/tree/").get(repo_tree); app.at("/:repo_name/tree/:ref").get(repo_tree); // ref is optional diff --git a/templates/log.xml b/templates/log.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<rss version="2.0"> + <channel> + <title>{{repo|repo_name}} {{branch}} commits</title> + <link>{{base_url}}/log</link> + <description> + Not more than the last 100 commits to the branch {{branch}} 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 commit in commits %} + <item> + <title>{{commit.summary().unwrap_or("")}}</title> + <link>{{base_url}}/commit/{{commit.id()}}</link> + <description>&lt;pre&gt;{{commit.message().unwrap_or("")}}&lt;/pre&gt;</description> + <author>{{commit.author().email().unwrap_or("")}}</author> + <pubDate>{{commit.time()|format_datetime("%a, %e %b %Y %T %z")}}</pubDate> + </item> + {% endfor %} + </channel> +</rss>