forked from lix-project/hydra
* Pretty-print the logs.
This commit is contained in:
parent
f6462ff5bb
commit
1f90d94331
|
@ -340,12 +340,12 @@ sub nixlog :Local {
|
||||||
|
|
||||||
sub loadLog {
|
sub loadLog {
|
||||||
my ($path) = @_;
|
my ($path) = @_;
|
||||||
# !!! all a quick hack
|
|
||||||
if ($path =~ /.bz2$/) {
|
# !!! quick hack
|
||||||
return `cat $path | bzip2 -d`;
|
my $pipeline = ($path =~ /.bz2$/ ? "cat $path | bzip2 -d" : "cat $path")
|
||||||
} else {
|
. " | nix-log2xml | xsltproc xsl/mark-errors.xsl - | xsltproc xsl/log2html.xsl - | tail -n +2";
|
||||||
return `cat $path`;
|
|
||||||
}
|
return `$pipeline`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -400,8 +400,8 @@ sub closure :Local {
|
||||||
$c->stash->{storePath} = $product->path;
|
$c->stash->{storePath} = $product->path;
|
||||||
$c->stash->{name} = $build->nixname;
|
$c->stash->{name} = $build->nixname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sub end : ActionClass('RenderView') {}
|
sub end : ActionClass('RenderView') {}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>[% title %]</title>
|
<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/jquery-pack.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/tablesorter/jquery.tablesorter.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">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$("table.tablesorter").tablesorter();
|
$("table.tablesorter").tablesorter();
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
<h1>Build log [% IF step %] of step [% step.stepnr %] [% ELSE %]<tt>[% log.logphase %]</tt>[% END %] of build ID [% id %]</h1>
|
<h1>Build log [% IF step %] of step [% step.stepnr %] [% ELSE %]<tt>[% log.logphase %]</tt>[% END %] of build ID [% id %]</h1>
|
||||||
|
|
||||||
<!-- !!! escaping -->
|
<!-- !!! escaping -->
|
||||||
<pre class="buildlog">
|
<div class="buildlog">
|
||||||
[% logtext -%]
|
[% logtext -%]
|
||||||
</pre>
|
</div>
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
|
@ -159,6 +159,11 @@ pre.buildlog {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.buildlog {
|
||||||
|
border: 1px solid black;
|
||||||
|
padding: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
ul.productList {
|
ul.productList {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding-left: 1em;
|
padding-left: 1em;
|
84
src/HydraFrontend/root/static/css/logfile.css
Normal file
84
src/HydraFrontend/root/static/css/logfile.css
Normal file
|
@ -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;
|
||||||
|
}
|
50
src/HydraFrontend/root/static/js/treebits.js
Normal file
50
src/HydraFrontend/root/static/js/treebits.js
Normal file
|
@ -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 = '';
|
||||||
|
}
|
||||||
|
}
|
74
src/HydraFrontend/xsl/log2html.xsl
Normal file
74
src/HydraFrontend/xsl/log2html.xsl
Normal file
|
@ -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>
|
24
src/HydraFrontend/xsl/mark-errors.xsl
Normal file
24
src/HydraFrontend/xsl/mark-errors.xsl
Normal file
|
@ -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>
|
Loading…
Reference in a new issue