view contrib/sawmill/web/details.py @ 557:9824e409388b

Refactor git branching If a checkout is already available and the branch is changed in the config git command would always fail because it doesn't know the branch to track. Therefore always check if the branch is locally available and if not checkout the remote branch
author Bjoern Ricks <bricks@intevation.de>
date Fri, 02 Sep 2011 08:45:28 +0000
parents 73a2e603a23b
children
line wrap: on
line source
# -*- 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.

from mod_python import apache, psp, util

import os
import re
import datetime
import time

from lxml import etree

BASE_DIR = "treepkgs"

TREEPKG_DIR = os.path.join(os.path.dirname(__file__), BASE_DIR)

STATUS_LINE = re.compile(r"^([^:]+):(.+)")

UNDER_SCORE = re.compile(r"_+(\w)")

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

def _create_time(s, format="%Y-%m-%d %H:%M:%S"):
    return datetime.datetime(*(time.strptime(s, format)[0:6]))

def _pretty_log_name(log):
    log = log.replace(".txt", "").replace(".gz", "").capitalize()
    return UNDER_SCORE.sub(lambda x: " %s" % x.group(1).upper(), log)

def _make_valid_label(label):
    return INVALID_LABEL.sub("_", label)

class TrackItem(object):

    def __init__(self, treepkg, track, revision, status_file):
        self.treepkg     = treepkg
        self.track       = track
        self.revision    = revision
        self.status_file = status_file
        self.loaded      = False
        self.status      = None
        self.start       = None
        self.stop        = None
        self.logs        = None
        self.tags        = None

    def check_loaded(self):
        if not self.loaded:
            f = open(self.status_file)
            try:
                for line in f:
                    m = STATUS_LINE.match(line)
                    if not m: continue
                    key, value = [x.strip() for x in m.groups()]

                    if   key == 'status': self.status = value
                    elif key == 'start':  self.start  = _create_time(value)
                    elif key == 'stop':   self.stop   = _create_time(value)
                    elif key == 'tags':   self.tags   = value
            finally:
                f.close()
            self.loaded = True

    def get_build_status(self):
        self.check_loaded()
        return self.status

    def get_build_start(self):
        self.check_loaded()
        return self.start

    def get_build_stop(self):
        self.check_loaded()
        return self.stop

    def get_tags(self):
        self.check_loaded()
        return self.tags

    def get_label(self):
        self.check_loaded()
        out = [
            _make_valid_label(self.track),
            _make_valid_label(self.revision) ]
        if self.start:
            out.append(self.start.strftime("%Y%m%d%H%M%S"))
        return ''.join(out)

    def log_path(self, log):
        return "%s/tracks/%s/pkg/%s/log/%s" % (
            self.treepkg, self.track, self.revision, log)

    def get_build_logs(self):
        oj = os.path.join
        if self.logs is None:
            log_dir = oj(os.path.dirname(self.status_file), "log")
            if not os.path.isdir(log_dir):
                self.logs = []
            else:
                self.logs =[(_pretty_log_name(f), self.log_path(f))
                    for f in os.listdir(log_dir)
                    if os.path.isfile(oj(log_dir, f)) and f.find("txt") >= 0]
        return self.logs

    build_status = property(get_build_status)
    build_start  = property(get_build_start)
    build_stop   = property(get_build_stop)
    build_logs   = property(get_build_logs)
    build_tags   = property(get_tags)
    build_label  = property(get_label)


def __scan_track_items(treepkg, path):
    items = []

    tracks_path = os.path.join(path, "tracks")
    if os.path.isdir(tracks_path):
        for track in os.listdir(tracks_path):
            track_path = os.path.join(tracks_path, track)
            if not os.path.isdir(track_path): continue
            revisions_path = os.path.join(track_path, "pkg")
            if not os.path.isdir(revisions_path): continue
            for revision in os.listdir(revisions_path):
                revision_path = os.path.join(revisions_path, revision)
                if not os.path.isdir(revision_path): continue
                status_file = os.path.join(revision_path, "status")
                if not os.path.isfile(status_file): continue
                items.append(TrackItem(treepkg, track, revision, status_file))

    return items

def __description_header(treepkg):
    treepkg_xml = os.path.join(treepkg, "treepkg.xml")
    if os.path.isfile(treepkg_xml):
        xml = None
        try:
            xml = open(treepkg_xml, "rb")
            dom = etree.parse(xml)
        finally:
            if xml: xml.close()

        description = ''.join(dom.xpath("//description/text()"))
        header = ''.join([etree.tostring(x, encoding="UTF-8", method="html")
            for x in dom.xpath("//header/*")])
        return description, header
    return "unknown", ""

def index(req, treepkg=''):
    if not treepkg: util.redirect(req, "index.py")

    package_dir = None
    for d in os.listdir(TREEPKG_DIR):
        dp = os.path.join(TREEPKG_DIR, d)
        if d == treepkg and os.path.isdir(dp):
            package_dir = dp
            break

    if not package_dir:
        req.status = apache.HTTP_NOT_FOUND
        return "requested TreePkg not found"

    description, header = __description_header(package_dir)

    track_items = __scan_track_items(treepkg, package_dir)

    parameters = {
        'page_title' : description,
        'back_link'  : 'index.py',
        'base_dir'   : BASE_DIR,
        'description': description,
        'header'     : header,
        'track_items': track_items
    }

    if os.path.isfile(os.path.join(package_dir, "rss.xml")):
        parameters['syndicate'] = (
            'Build error feed',
            'treepkgs/%s/rss.xml' % treepkg)

    req.content_type = 'text/html;charset=utf-8'
    template = psp.PSP(req, filename='templates/details.html')
    template.run(parameters)
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)