changeset 21:52a1d74084a6

merge
author Bernhard Herzog <bh@intevation.de>
date Tue, 13 Mar 2007 19:32:21 +0100
parents 467013d9d627 (diff) 6ced445aa090 (current diff)
children 687fc0b9f97e
files
diffstat 6 files changed, 274 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/reportstatus.py	Mon Mar 12 15:24:18 2007 +0100
+++ b/reportstatus.py	Tue Mar 13 19:32:21 2007 +0100
@@ -11,8 +11,7 @@
 import os
 from optparse import OptionParser
 
-from treepkg.packager import create_package_line, PackagerGroup
-from treepkg.readconfig import read_config
+from treepkg.report import get_packager_group, prepare_report
 
 def parse_commandline():
     parser = OptionParser()
@@ -21,17 +20,22 @@
     parser.add_option("--config-file")
     return parser.parse_args()
 
+
+def report_text(group):
+    report = prepare_report(group)
+    for revno, row in report.revisions:
+        for col in row:
+            if col:
+                print "%s %s: %s" % (col.name, revno, col.status.desc)
+                if col.status.start:
+                    print "    Start:", col.status.start
+                    print "     Stop:", col.status.stop
+                print
+
 def main():
     options, args = parse_commandline()
+    group = get_packager_group(options.config_file)
+    report_text(group)
 
-    treepkg_opts, packager_opts = read_config(options.config_file)
-    group = PackagerGroup([create_package_line(**opts)
-                           for opts in packager_opts],
-                          **treepkg_opts)
-    for line in group.get_package_lines():
-        for revision in line.get_revisions():
-            print line.name, revision.revision, revision.status.status
-            print "    start:", revision.status.start
-            print "     stop:", revision.status.stop
 
 main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/starttreepkgweb.py	Tue Mar 13 19:32:21 2007 +0100
@@ -0,0 +1,33 @@
+#! /usr/bin/python2.4
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh@intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Starts the tree packager webinterface"""
+
+import os
+from optparse import OptionParser
+
+from treepkg.web import runserver
+
+def parse_commandline():
+    parser = OptionParser()
+    dirname = os.path.dirname(__file__)
+    parser.set_defaults(config_file=os.path.join(dirname, "treepkg.cfg"),
+                        cherrypy_config=os.path.join(dirname, "cherrypy.cfg"))
+    parser.add_option("--config-file",
+                      help=("The tree packager config file."
+                            " Default treepkg.cfg"))
+    parser.add_option("--cherrypy-config",
+                      help=("The cherrypy config file for the web interface."
+                            " Default cherrypy.cfg"))
+    return parser.parse_args()
+
+def main():
+    options, args = parse_commandline()
+    runserver(options.config_file, options.cherrypy_config)
+
+main()
--- a/treepkg/packager.py	Mon Mar 12 15:24:18 2007 +0100
+++ b/treepkg/packager.py	Tue Mar 13 19:32:21 2007 +0100
@@ -205,6 +205,7 @@
     work_dir = _filenameproperty("work")
     binary_dir = _filenameproperty("binary")
     src_dir = _filenameproperty("src")
+    build_log = _filenameproperty("build.log")
 
     def find_dsc_file(self):
         for filename in os.listdir(self.src_dir):
@@ -212,6 +213,9 @@
                 return os.path.join(self.src_dir, filename)
         return None
 
+    def has_build_log(self):
+        return os.path.exists(self.build_log)
+
     def package(self):
         try:
             util.ensure_directory(self.work_dir)
@@ -227,8 +231,7 @@
 
             bin_packager = self.binary_packager_cls(self.pkg_line, self.status,
                                                     self.binary_dir, dsc_file,
-                                                    os.path.join(self.base_dir,
-                                                                 "build.log"))
+                                                    self.build_log)
             bin_packager.package()
             self.status.stop = datetime.datetime.utcnow()
         except:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/treepkg/report.py	Tue Mar 13 19:32:21 2007 +0100
@@ -0,0 +1,97 @@
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh@intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+"""Support for status reports"""
+
+from packager import create_package_line, PackagerGroup
+from readconfig import read_config
+
+class struct(object):
+
+    """Class to create simple struct like objects
+
+    All keyword arguments passed to the constructor are available as
+    instance variables.
+    """
+
+    def __init__(self, **kw):
+        self.__dict__.update(kw)
+
+    def __repr__(self):
+        fields = ["%s=%r" % item for item in self.__dict__.items()]
+        return "struct(" + ", ".join(fields)  + ")"
+
+
+def get_packager_group(config_file):
+    treepkg_opts, packager_opts = read_config(config_file)
+    return PackagerGroup([create_package_line(**opts)
+                          for opts in packager_opts],
+                         **treepkg_opts)
+
+status_expansions = dict(
+    binary_package_created="build successful",
+    creating_binary_package="building binary packages",
+    source_package_created="source package created",
+    creating_source_package="creating source package",
+    error="error")
+
+def status_finished(status):
+    return status.status == "binary_package_created"
+
+def status_error(status):
+    return status.status == "error"
+
+def status_class(status):
+    """Returns the CSS class for a status"""
+    if status_finished(status):
+        return "finished"
+    elif status_error(status):
+        return "error"
+    else:
+        return "inprogress"
+
+def format_time(timestamp):
+    """Formats a datetime object for a status report
+
+    if the argument is true, the return value is simply str applied to
+    the argument, which for datetime objects is a string with the format
+    'YYYY-MM-DD hh:mm:ss'.  If the argument is false, the return value
+    is '<unknown>'.
+    """
+    if timestamp:
+        return str(timestamp)
+    else:
+        return "<unknown>"
+
+
+def prepare_status(status):
+    return struct(desc=status_expansions.get(status.status,
+                                             status.status),
+                  start=format_time(status.start),
+                  stop=format_time(status.stop),
+                  cls=status_class(status))
+
+def prepare_report(group):
+    revisions = []
+    columns = []
+    pkglines = group.get_package_lines()
+    num_columns = len(pkglines)
+    for column, line in enumerate(pkglines):
+        columns.append((column, line.name))
+        for revision in line.get_revisions():
+            row = [None] * num_columns
+            row[column] = struct(revno=revision.revision,
+                                 revision=revision,
+                                 column=column,
+                                 name=line.name,
+                                 status=prepare_status(revision.status))
+            revisions.append((revision.revision, row))
+    revisions.sort()
+    revisions.reverse()
+
+    return struct(columns=columns,
+                  revisions=revisions)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/treepkg/web-status.html	Tue Mar 13 19:32:21 2007 +0100
@@ -0,0 +1,53 @@
+<html xmlns:py="http://genshi.edgewall.org/">
+  <head>
+    <title>Tree Packager Status</title>
+    <style type="text/css">
+      .statustable { background:#F4F4F4; }
+      .statustablehead { background:#E0E0E0; }
+      .statusheading { font-weight:bold; }
+      .finished { background:#C0FFC0; }
+      .inprogress { background:#FFFFC0; }
+      .error { background:#FFC0C0; }
+      td { padding:5px; background:#FFFFFF}
+    </style>
+  </head>
+  <body>
+    <h1>Tree Packager Status</h1>
+
+    <table class="statustable">
+      <tr>
+	<th class="statustablehead">Revision</th>
+	<py:for each="col in report.columns">
+	  <th class="statustablehead">${col[1]}</th>
+	</py:for>
+      </tr>
+
+      <py:for each="row in report.revisions">
+	<tr>
+	  <td>${row[0]}</td>
+	  <py:for each="col in row[1]">
+	    <py:choose>
+	      <py:when test="col">
+		<td class="${col.status.cls}">
+		  <span class="statusheading">${col.status.desc}</span><br/>
+		  Start: ${col.status.start}<br/>
+		  Stop: ${col.status.stop}<br/>
+		  <py:if test="col.revision.has_build_log">
+		    <a href="${col.name}/${col.revno}/build.log">build_log</a>
+		  </py:if>
+		</td>
+	      </py:when>
+	      <py:otherwise>
+		<td></td>
+	      </py:otherwise>
+	    </py:choose>
+	  </py:for>
+
+	</tr>
+      </py:for>
+    </table>
+
+    All times are given in UTC.
+
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/treepkg/web.py	Tue Mar 13 19:32:21 2007 +0100
@@ -0,0 +1,71 @@
+# Copyright (C) 2007 by Intevation GmbH
+# Authors:
+# Bernhard Herzog <bh@intevation.de>
+#
+# This program is free software under the GPL (>=v2)
+# Read the file COPYING coming with the software for details.
+
+import os
+
+from genshi.template import TemplateLoader
+
+import cherrypy
+from cherrypy import expose
+from cherrypy.lib import cptools
+
+import report
+
+
+class Status(object):
+
+    """Implements the tree packager status pages"""
+
+    def __init__(self, treepkg_config):
+        self.treepkg_config = treepkg_config
+        self.loader = TemplateLoader([os.path.dirname(__file__)])
+
+    @expose
+    def index(self):
+        group = report.get_packager_group(self.treepkg_config)
+        tmpl = self.loader.load('web-status.html')
+        stream = tmpl.generate(report=report.prepare_report(group))
+        return stream.render('html')
+
+    def build_log_filename(self, package_line_name, revno):
+        """Returns the name of the build log file of a revision if it exists"""
+        group = report.get_packager_group(self.treepkg_config)
+        for line in group.get_package_lines():
+            if line.name == package_line_name:
+                for revision in line.get_revisions():
+                    if str(revision.revision) == revno:
+                        if revision.has_build_log():
+                            return revision.build_log
+
+    @expose
+    def default(self, *rest):
+        """Handles requests for .../pkg/revno/build.log"""
+        filename = None
+        if len(rest) == 3 and rest[2] == "build.log":
+            filename = self.build_log_filename(*rest[:2])
+        if filename is not None:
+            return cptools.serveFile(filename, contentType="text/plain")
+        else:
+            raise cherrypy.HTTPError(status="404")
+
+
+
+class TreePKG(object):
+
+    """Root object for the tree packager web interface"""
+
+    @expose
+    def index(self):
+        raise cherrypy.HTTPRedirect('/status')
+
+
+def runserver(treepkg_config, cherrypy_config):
+    cherrypy.root = TreePKG()
+    cherrypy.root.status = Status(treepkg_config=treepkg_config)
+
+    cherrypy.config.update(file=cherrypy_config)
+    cherrypy.server.start()
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)