#!/usr/bin/python -u # vim: set fileencoding=utf-8 : # # (C) 2008 Guido Guenther # 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 # """Link Debian changelog entries to the VCS""" import cgi import os import re import sys import urlgrabber from lxml import etree from genshi.template import TemplateLoader import vcsbrowsers from htmlchangelog import HTMLChangelog VERSION="0.0.3" XMLNS='http://www.w3.org/1999/xhtml' PTS='http://packages.qa.debian.org' PKGNAMERE="[a-zA-Z0-9.+\-]+$" def fetch_changelog(cl_url): changelog = urlgrabber.urlread(cl_url, timeout=5.0).decode('utf-8') return changelog def fetch_pts_page(package): pts = None try: url = "%s/%s" % (PTS, package) pts = urlgrabber.urlopen(url, timeout=5.0) except urlgrabber.grabber.URLGrabError as (code, msg): if code == 14: raise Exception, "Can't find package '%s' on '%s'" % (package, PTS) else: raise return pts def parse_pts_xhtml(pts): cl_url = None vcs_url = None vcs = None tree = etree.parse(pts) searcher = etree.ETXPath('/{%s}html/{%s}body//{%s}a[@href]' % (XMLNS, XMLNS, XMLNS)) result = searcher(tree) for r in result: if not r.text: continue if r.text.lower() == "changelog": cl_url = r.attrib['href'] elif r.text.lower() == "browse": vcs_url = r.attrib['href'] parent = r.getparent() vcs = parent.getchildren()[0].text.lower() return cl_url, vcs_url, vcs def get_vcsbrowser(vcs, vcs_url): if vcs == "git": return vcsbrowsers.GitWebBrowser(vcs_url) elif vcs == "Mercurial": return vcsbrowsers.HgBrowser(vcs_url) def render_search_page(title, pkg=None, err=None): loader = TemplateLoader('templates') tmpl = loader.load('index.html') print tmpl.generate(title=title, pkg=pkg, err=err).render('xhtml', doctype='xhtml-strict') def render_changelog_page(cl): print cl def main(argv): title = "cl2vcs %s" % VERSION err = "" print "Content-Type: text/html; charset=utf-8" print try: form = cgi.FieldStorage() if form.has_key('pkg'): pkg = form.getfirst('pkg').decode('utf-8').strip() else: pkg = None if pkg: if not re.match(PKGNAMERE, pkg): return render_search_page(title=title, err=u"Invalid package name: '%s'" % pkg) else: pkg = str(pkg) else: return render_search_page(title=title, err=err) try: pts = fetch_pts_page(pkg) except Exception as exc_err: err = exc_err pts = None if not pts: return render_search_page(title=title, pkg=pkg, err=err) cl_url, vcs_url, vcs = parse_pts_xhtml(pts) if cl_url == None: return render_search_page(title=title, pkg=pkg, err="Cannot parse changelog from PTS page.") try: cl_text = fetch_changelog(cl_url) except urlgrabber.grabber.URLGrabError, (errcode, errmsg): return render_search_page(title=title, err="Cannot fetch '%s': %s" % (cl_url, errmsg)) if vcs and vcs_url: vcsbrowser = get_vcsbrowser(vcs, vcs_url) else: vcsbrowser = None cl = HTMLChangelog(cl_text, vcsbrowser=vcsbrowser) if cl: render_changelog_page(cl) except Exception, err: import traceback traceback.print_exc(file=sys.stderr) render_search_page(title=title, err="Unknown error") return 0 if __name__ == "__main__": sys.exit(main(sys.argv))