File modified: Makefile bin/blog-archive.py bin/hg2rss.py
Change350 at Sun Aug 22 19:43:53 2010 +0200 by Ivan Kanis <ivan@tao>
diff -r 03aeefb078f8 -r 79d7e6c3575c bin/hg2rss.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/hg2rss.py Sun Aug 22 19:43:53 2010 +0200 @@ -0,0 +1,257 @@ +#!/usr/bin/env python +# turn hg log into rss +# -*- coding: utf-8 -*- + +import os, re, cgi + +home = os.getenv("HOME") +web_dir = home + "/hg/web/" +single_page_dir = web_dir + "hgrss/" + +matches = {'changeset' : re.compile("changeset: (.*):"), + 'user' : re.compile("user: (.*)"), + 'date' : re.compile("date: (.*)"), + 'files' : re.compile("files: (.*)"), + } + +def output_prelude_xml(out_xml): + out_xml.write("""<?xml version="1.0" encoding="utf-8"?> +<rss version="2.0"> + <channel> + <title>Mercurial commits</title> + <link>http://kanis.fr/hg.html</link> + <description>List of Mercurial commits</description> + <language>en-us</language> + <generator>hg2rss.py</generator>""") + +def output_prelude_html(out_html, title, big_page=True): + out_html.write( + """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<html> + <head> + <title>""" + title + """</title> + <meta name="generator" content="hg2rsss.py"> + <meta http-equiv="Content-Type" + content="text/html; charset=utf-8"> + <link rel="stylesheet" +type="text/css" charset="utf-8" media="all" href=""") + if big_page: + out_html.write("\"kanis.css\">") + else: + out_html.write("\"../kanis.css\">") + out_html.write("""<link rel="icon" href="ik16.png" type="image/png"> + </head> + <body> + <h1>""" + title + """</h1> + <!-- Page published by hg2rss.py begins here --> +""") + +def output_end_xml(out_xml): + out_xml.write(""" </channel> +</rss>""") + +def output_end_html(out_html): + out_html.write(""" + </body> +</html>""") + +def output_html(out_html, value, str_desc, descriptions, big_page=True): + output_html2(out_html, big_page, """ +<div class="entry"> + <a name=""" + str_desc + """ style="text-decoration: none"> </a>""") + if big_page: + output_html2(out_html, big_page, """ + <h2>""" + descriptions[0] + """</h2>""") + output_html2(out_html, big_page, """ + <p class="first">""" + "\n".join(descriptions[1:]) + """</p> + <p>File modified: """ + value["files"] + """ + <p>""") + if big_page: + output_html2(out_html, big_page, "<a href=hgrss/" + value["changeset"] + + ".html>") + output_html2(out_html, big_page, "Change" + value["changeset"]) + if big_page: + output_html2(out_html, big_page, "</a>") + output_html2(out_html, big_page, " at " + value["date"] + + " by " + value["user"] + """</p> +""") + count = 0 + output_html2(out_html, big_page, "<pre>\n") + for line in value["diff"].split("\n"): + if line[:3] == "+++" or line[:3] == "---": + output_html2(out_html, big_page, line + "\n") + elif line[:1] == "+": + output_html2(out_html, big_page, "<span class=\"green\">" + + line + + "</span>\n") + elif line[:1] == "-": + output_html2(out_html, big_page, "<span class=\"red\">" + + line + + "</span>\n") + else: + output_html2(out_html, big_page, line + "\n") + count += 1 + if big_page and count > 40: + output_html2(out_html, big_page, """...\n""") + break + + output_html2(out_html, big_page, "</pre>\n</div>\n") + if not big_page: + output_html2(out_html, big_page,"<p><a href=../hg.html#" + + str_desc + ">back</a>") + +def output_html2(out_html, big_page, string): + if big_page: + for f in out_html: + f.write(string) + else: + out_html.write(string) + +def output_entry(out_xml, out_html, value): + if "description" in value: + descriptions = value["description"].split("\n") + str_desc =descriptions[0].replace(" ", "%20") + for f in out_xml: + f.write(""" + <item>\n + <title>""" + descriptions[0] + """</title> + <link>http://kanis.fr/hg.html#""" + str_desc + """</link> + <description><![CDATA[ + <p>""" + "\n".join(descriptions[1:]) + """</p> + ]]></description> + <author>Ivan Kanis</author> + <pubDate>""" + value["date"] + """</pubDate> + <guid>hg.html#""" + str_desc + """</guid> + </item>""") + output_html(out_html, value, str_desc, descriptions) + change_page = open(single_page_dir + + value["changeset"] + ".html", "w") + output_prelude_html(change_page, descriptions[0], False) + output_html(change_page, value, str_desc, descriptions, False) + output_end_html(change_page) + change_page.close() + +def init_value(): + return { 'files' : "", + 'user' : "", + 'date' : "", + 'changeset' : "", + 'diff' : "", + 'description' : "" } + +def parse_log(last_revision): + if last_revision == 0: + f = os.popen("hg log -r 2: -v -p") + else: + f = os.popen("hg log -r " + str(last_revision) + ": -v -p") + value = init_value() + values = [] + b_desc = False + b_diff = False + for line in f: + if len(line) > 10 and line[:10] == "changeset:": + values.append(value) + value = init_value() + b_desc = False + b_diff = False + if len(line) == 13 and line[:12] == "description:": + b_desc = True + value["description"] = "" + elif len(line) > 7 and line[:7] == "diff -r": + b_diff = True + b_desc = False + value["diff"] = cgi.escape(line) + elif b_desc: + value["description"] += cgi.escape(line) + elif b_diff: + value["diff"] += cgi.escape(line) + else: + for (v,k) in matches.iteritems(): + match = k.match(line) + if match: + value[v] = cgi.escape(match.groups()[0]) + continue + values.append(value) + return values + +def main(last_revision): + cache_xml = "hg-xml.cache" + cache_html = "hg-html.cache" + cache = False + if os.path.exists(cache_xml) and os.path.exists(cache_html): + f = open(cache_xml, "r") + cache_xml_content = f.read() + f.close() + f = open(cache_html, "r") + cache_html_content = f.read() + f.close() + cache = True + out_xml = [open(web_dir + "hg.xml", "w"), + open(cache_xml, "w")] + out_html = [open(web_dir + "hg.html", "w"), + open(cache_html, "w")] + output_prelude_xml(out_xml[0]) + output_prelude_html(out_html[0], "Mercurial Commits") + if cache: + values = parse_log(int(last_revision)+1) + else: + values = parse_log(0) + # walk the changes backward + for i in range(len(values)-1, 0, -1): + output_entry(out_xml, out_html, values[i]) + if cache: + for i in [0, 1]: + out_xml[i].write(cache_xml_content) + out_html[i].write(cache_html_content) + output_end_xml(out_xml[0]) + output_end_html(out_html[0]) + + +if __name__ == "__main__": + f = os.popen("hg log -l 1") + r = re.compile("changeset: (.*):") + m = r.match(f.read()) + if m: + revision = m.groups()[0] + else: + print "Impossible to find last revision." + exit (1) + f.close() + stamp = "hg2rss.stamp" + last_revision = "" + if os.path.exists(stamp): + f = open(stamp, "r") + last_revision = f.read() + f.close() + if revision == last_revision: + print "same revision." + else: + main(last_revision) + else: + main(last_revision) + f = open(stamp, "w") + f.write(revision) + f.close() + + +# Local Variables: +# compile-command: "python hg2rss.py" +# End: + +# Copyright (C) 2009 Ivan Kanis +# Author: Ivan Kanis +# +# +# This program is free software ; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation ; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY ; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program ; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA