view contrib/sawmill/bin/generate-rss.py @ 578:bccd69dedbe5

shlex.split all config parameters that may contain a command Return the command as list and use @ operator for the variable in cmdexpand
author Bjoern Ricks <bricks@intevation.de>
date Sat, 03 Sep 2011 11:53:12 +0000
parents 93d66243bce7
children
line wrap: on
line source
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#
# Copyright (C) 2010 by Intevation GmbH
# Authors:
# Sascha L. Teichmann <sascha.teichmann@intevation.de>
#
# This program is free software under the GPL (>=v2)
# Read the file COPYING coming with the software for details.

import sys
import os
import re
import traceback

from datetime import datetime

from lxml import etree

import PyRSS2Gen as RSS2

BASE_URL = "http://saegewerk2.wald.intevation.org/buildlogs"
LINK_URL = "%s/details.py?treepkg=%%s" % BASE_URL
ITEM_URL = "%s/details.py?treepkg=%%s#%%s" % BASE_URL

TITLE       = "Saegewerk - %s"
DESCRIPTION = "Build errors of '%s'"
MESSAGE     = "%s: error building %s rev. %s"
TTL         = 7

START = re.compile(
    r"start:\s+(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})")
STATUS = re.compile(r"status:\s+(.+)")

INVALID_LABEL = re.compile(r"[^a-zA-Z0-9_]")

def make_valid_label(l):
    return INVALID_LABEL.sub("_", l)

def to_datetime(m):
    m = map(int, m.groups())
    return datetime(
        year=m[0], month=m[1], day=m[2], 
        hour=m[3], minute=m[4], second=m[5])

def usage(msg, code=1):
    print >> sys.stderr, "%s <treepkgs directory>" % sys.argv[0]
    print >> sys.stderr, "%s" % msg
    sys.exit(code)

def main():
    if len(sys.argv) < 2:
        usage("missing treepkgs directory")

    treepkgs_dir = sys.argv[1]
    if not os.path.isdir(treepkgs_dir):
        usage("'%s' is not a directory" % treepkgs_dir)

    for treepkg in os.listdir(treepkgs_dir):
        treepkg_dir = os.path.join(treepkgs_dir, treepkg)
        if not os.path.isdir(treepkg_dir): continue
        treepkg_xml = os.path.join(treepkg_dir, "treepkg.xml")
        if not os.path.isfile(treepkg_xml): continue
        try:
            f = open(treepkg_xml, "rb")
            try:     treepkg_dom = etree.parse(f)
            finally: f.close()
        except:
            traceback.print_exc(file=sys.stderr)
            continue
        description = ''.join(
            treepkg_dom.xpath('/treepkg/description/text()'))

        tracks_dir = os.path.join(treepkg_dir, "tracks")
        if not os.path.isdir(tracks_dir): continue

        items = []

        for track in os.listdir(tracks_dir):
            track_dir = os.path.join(tracks_dir, track, "pkg")
            if not os.path.isdir(track_dir): continue

            track_label = make_valid_label(track)

            for revision in os.listdir(track_dir):
                revision_dir = os.path.join(track_dir, revision)
                if not os.path.isdir(revision_dir): continue
                status_file = os.path.join(revision_dir, "status")
                if not os.path.isfile(status_file): continue
                start, status = None, None
                try:
                    f = open(status_file, "r")
                    try:
                        while True:
                            line = f.readline()
                            if not line: break
                            m = STATUS.match(line)
                            if m: status = m.group(1); continue
                            m = START.match(line)
                            if m: start = to_datetime(m)
                    finally:
                        f.close()
                except:
                    traceback.print_exc(file=sys.stderr)
                    continue
                if status != "error" or not start: continue

                label = ''.join([
                    track_label,
                    make_valid_label(revision),
                    start.strftime("%Y%m%d%H%M%S")])

                link = ITEM_URL % (treepkg, label)
                msg  = MESSAGE  % (description, track, revision)
                item = RSS2.RSSItem(
                    title       = msg,
                    link        = link,
                    description = msg,
                    guid        = RSS2.Guid(link, isPermaLink=0),
                    pubDate     = start
                )
                items.append(item)

        items.sort(key=lambda x: x.pubDate)

        rss = RSS2.RSS2(
            title       = TITLE % description,
            link        = LINK_URL % treepkg,
            description = DESCRIPTION % description,
            pubDate     = datetime.utcnow(),
            ttl         = TTL,
            items       = items)

        pid, idx = os.getpid(), 0
        while True:
            tmp_f = os.path.join(
                treepkg_dir, "rss.xml.tmp%d-%d" % (pid, idx))
            if not os.path.exists(tmp_f): break
            idx += 1

        try:
            f = open(tmp_f, "wb")
            try: rss.write_xml(f, encoding="UTF-8")
            finally: f.close()

            rss_xml = os.path.join(treepkg_dir, "rss.xml")

            os.rename(tmp_f, rss_xml)
        except:
            traceback.print_exc(file=sys.stderr)
            if os.path.exists(tmp_f):
                try: os.remove(tmp_f)
                except: pass

if __name__ == '__main__':
    main()
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)