From 1f90d94331784c4186933aed53a443361e4cd4d2 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra <e.dolstra@tudelft.nl> Date: Tue, 18 Nov 2008 16:45:23 +0000 Subject: [PATCH] * Pretty-print the logs. --- .../lib/HydraFrontend/Controller/Root.pm | 16 ++-- src/HydraFrontend/root/layout.tt | 4 +- src/HydraFrontend/root/log.tt | 4 +- .../root/{ => static/css}/hydra.css | 5 ++ src/HydraFrontend/root/static/css/logfile.css | 84 +++++++++++++++++++ src/HydraFrontend/root/static/js/treebits.js | 50 +++++++++++ src/HydraFrontend/xsl/log2html.xsl | 74 ++++++++++++++++ src/HydraFrontend/xsl/mark-errors.xsl | 24 ++++++ 8 files changed, 250 insertions(+), 11 deletions(-) rename src/HydraFrontend/root/{ => static/css}/hydra.css (98%) create mode 100644 src/HydraFrontend/root/static/css/logfile.css create mode 100644 src/HydraFrontend/root/static/js/treebits.js create mode 100644 src/HydraFrontend/xsl/log2html.xsl create mode 100644 src/HydraFrontend/xsl/mark-errors.xsl diff --git a/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm b/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm index 05b8ce9b..bb668242 100644 --- a/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm +++ b/src/HydraFrontend/lib/HydraFrontend/Controller/Root.pm @@ -340,12 +340,12 @@ sub nixlog :Local { sub loadLog { my ($path) = @_; - # !!! all a quick hack - if ($path =~ /.bz2$/) { - return `cat $path | bzip2 -d`; - } else { - return `cat $path`; - } + + # !!! quick hack + my $pipeline = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path") + . " | nix-log2xml | xsltproc xsl/mark-errors.xsl - | xsltproc xsl/log2html.xsl - | tail -n +2"; + + return `$pipeline`; } @@ -400,8 +400,8 @@ sub closure :Local { $c->stash->{storePath} = $product->path; $c->stash->{name} = $build->nixname; } - - + + sub end : ActionClass('RenderView') {} diff --git a/src/HydraFrontend/root/layout.tt b/src/HydraFrontend/root/layout.tt index 90f3e57e..ff2bac99 100644 --- a/src/HydraFrontend/root/layout.tt +++ b/src/HydraFrontend/root/layout.tt @@ -14,9 +14,11 @@ <head> <title>[% title %]</title> - <link rel="stylesheet" href="/hydra.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/hydra.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/logfile.css" type="text/css" /> <script type="text/javascript" src="/static/js/jquery-pack.js"></script> <script type="text/javascript" src="/static/js/tablesorter/jquery.tablesorter.js"></script> + <script type="text/javascript" src="/static/js/treebits.js"></script> <script type="text/javascript"> $(document).ready(function() { $("table.tablesorter").tablesorter(); diff --git a/src/HydraFrontend/root/log.tt b/src/HydraFrontend/root/log.tt index 72702aa8..0874742f 100644 --- a/src/HydraFrontend/root/log.tt +++ b/src/HydraFrontend/root/log.tt @@ -3,8 +3,8 @@ <h1>Build log [% IF step %] of step [% step.stepnr %] [% ELSE %]<tt>[% log.logphase %]</tt>[% END %] of build ID [% id %]</h1> <!-- !!! escaping --> -<pre class="buildlog"> +<div class="buildlog"> [% logtext -%] -</pre> +</div> [% END %] diff --git a/src/HydraFrontend/root/hydra.css b/src/HydraFrontend/root/static/css/hydra.css similarity index 98% rename from src/HydraFrontend/root/hydra.css rename to src/HydraFrontend/root/static/css/hydra.css index 6ba2976f..ce7925c2 100644 --- a/src/HydraFrontend/root/hydra.css +++ b/src/HydraFrontend/root/static/css/hydra.css @@ -159,6 +159,11 @@ pre.buildlog { white-space: pre-wrap; } +div.buildlog { + border: 1px solid black; + padding: 0.3em; +} + ul.productList { list-style: none; padding-left: 1em; diff --git a/src/HydraFrontend/root/static/css/logfile.css b/src/HydraFrontend/root/static/css/logfile.css new file mode 100644 index 00000000..b4709048 --- /dev/null +++ b/src/HydraFrontend/root/static/css/logfile.css @@ -0,0 +1,84 @@ +ul.nesting, ul.toplevel { + padding: 0; + margin: 0; +} + +ul.toplevel { + list-style-type: none; +} + +.line, .head { + padding-top: 0em; +} + +ul.nesting li.line, ul.nesting li.lastline { + position: relative; + list-style-type: none; +} + +ul.nesting li.line { + padding-left: 2.0em; +} + +ul.nesting li.lastline { + padding-left: 2.1em; // for the 0.1em border-left in .lastline > .lineconn +} + +li.line { + border-left: 0.1em solid #6185a0; +} + +li.line > span.lineconn, li.lastline > span.lineconn { + position: absolute; + height: 0.65em; + left: 0em; + width: 1.5em; + border-bottom: 0.1em solid #6185a0; +} + +li.lastline > span.lineconn { + border-left: 0.1em solid #6185a0; +} + + +em.storeref { + color: #500000; + position: relative; + width: 100%; +} + +em.storeref:hover { + background-color: #eeeeee; +} + +*.popup { + display: none; +/* background: url('http://losser.st-lab.cs.uu.nl/~mbravenb/menuback.png') repeat; */ + background: #ffffcd; + border: solid #555555 1px; + position: absolute; + top: 0em; + left: 0em; + margin: 0; + padding: 0; + z-index: 100; +} + +em.storeref:hover span.popup { + display: inline; +} + + +.toggle { + text-decoration: none; +} + +.showTree, .hideTree { + font-family: monospace; + font-size: larger; +} + +.error { + color: #ff0000; + font-weight: bold; +} \ No newline at end of file diff --git a/src/HydraFrontend/root/static/js/treebits.js b/src/HydraFrontend/root/static/js/treebits.js new file mode 100644 index 00000000..3011b391 --- /dev/null +++ b/src/HydraFrontend/root/static/js/treebits.js @@ -0,0 +1,50 @@ +/* Acknowledgement: this is based on the Wikipedia table-of-contents + * toggle. */ + + +var idCounter = 0; + + +function showTreeToggle(isHidden) { + if (document.getElementById) { + var id = "toggle_" + idCounter; + document.writeln( + '<a href="javascript:toggleTree(\'' + id + '\')" class="toggle" id="' + id + '">' + + '<span class="showTree" ' + (isHidden ? '' : 'style="display: none;"') + '>+</span>' + + '<span class="hideTree" ' + (isHidden ? 'style="display: none;"' : '') + '>-</span>' + + '</a>'); + idCounter = idCounter + 1; + } +} + + +function toggleTree(id) { + + var href = document.getElementById(id); + + var node = href; + var tree = null; + while (node != null) { + if (node.className == "nesting") tree = node; + node = node.nextSibling; + } + + node = href.firstChild; + var hideTree = null; + var showTree = null; + while (node != null) { + if (node.className == "showTree") showTree = node; + else if (node.className == "hideTree") hideTree = node; + node = node.nextSibling; + } + + if (tree.style.display == 'none') { + tree.style.display = ''; + hideTree.style.display = ''; + showTree.style.display = 'none'; + } else { + tree.style.display = 'none'; + hideTree.style.display = 'none'; + showTree.style.display = ''; + } +} diff --git a/src/HydraFrontend/xsl/log2html.xsl b/src/HydraFrontend/xsl/log2html.xsl new file mode 100644 index 00000000..78532882 --- /dev/null +++ b/src/HydraFrontend/xsl/log2html.xsl @@ -0,0 +1,74 @@ +<?xml version="1.0"?> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:output method='html' encoding="UTF-8" + doctype-public="-//W3C//DTD HTML 4.01//EN" + doctype-system="http://www.w3.org/TR/html4/strict.dtd" /> + + <xsl:template match="logfile"> + <ul class='toplevel'> + <xsl:for-each select='line|nest'> + <li> + <xsl:apply-templates select='.'/> + </li> + </xsl:for-each> + </ul> + </xsl:template> + + + <xsl:template match="nest"> + + <!-- The tree should be collapsed by default if all children are + unimportant or if the header is unimportant. --> +<!-- <xsl:variable name="collapsed" + select="count(.//line[not(@priority = 3)]) = 0 or ./head[@priority = 3]" /> --> + <xsl:variable name="collapsed" select="count(.//*[@error]) = 0"/> + + <xsl:variable name="style"><xsl:if test="$collapsed">display: none;</xsl:if></xsl:variable> + <xsl:variable name="arg"><xsl:choose><xsl:when test="$collapsed">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:variable> + + <script type='text/javascript'>showTreeToggle(<xsl:value-of select="$collapsed"/>)</script> + <xsl:apply-templates select='head'/> + + <!-- Be careful to only generate <ul>s if there are <li>s, otherwise it’s malformed. --> + <xsl:if test="line|nest"> + + <ul class='nesting' style="{$style}"> + <xsl:for-each select='line|nest'> + + <!-- Is this the last line? If so, mark it as such so that it + can be rendered differently. --> + <xsl:variable name="class"><xsl:choose><xsl:when test="position() != last()">line</xsl:when><xsl:otherwise>lastline</xsl:otherwise></xsl:choose></xsl:variable> + + <li class='{$class}'> + <span class='lineconn' /> + <span class='linebody'> + <xsl:apply-templates select='.'/> + </span> + </li> + </xsl:for-each> + </ul> + </xsl:if> + + </xsl:template> + + + <xsl:template match="head|line"> + <code> + <xsl:if test="@error"> + <xsl:attribute name="class">error</xsl:attribute> + </xsl:if> + <xsl:apply-templates/> + </code> + </xsl:template> + + + <xsl:template match="storeref"> + <em class='storeref'> + <span class='popup'><xsl:apply-templates/></span> + <span class='elided'>/...</span><xsl:apply-templates select='name'/><xsl:apply-templates select='path'/> + </em> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file diff --git a/src/HydraFrontend/xsl/mark-errors.xsl b/src/HydraFrontend/xsl/mark-errors.xsl new file mode 100644 index 00000000..4e91913e --- /dev/null +++ b/src/HydraFrontend/xsl/mark-errors.xsl @@ -0,0 +1,24 @@ +<?xml version="1.0"?> + +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + + <xsl:template match="@*|node()"> + <xsl:copy> + <xsl:apply-templates select="@*|node()"/> + </xsl:copy> + </xsl:template> + + <xsl:template match="line"> + <line> + <xsl:if test="contains(text(), ' *** ') or + contains(text(), 'LaTeX Error') or + contains(text(), 'FAIL:') or + contains(text(), ' error: ') or + true"> + <xsl:attribute name="error"></xsl:attribute> + </xsl:if> + <xsl:apply-templates select="@*|node()"/> + </line> + </xsl:template> + +</xsl:stylesheet> \ No newline at end of file