summaryrefslogtreecommitdiffstats
path: root/reporting
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xreporting/checkout-release29
-rw-r--r--reporting/config.yaml72
-rw-r--r--reporting/graphs/statistics.gpi38
-rw-r--r--reporting/graphs/tags.gpi35
-rw-r--r--reporting/images/ico.pngbin0 -> 230 bytes
-rw-r--r--reporting/images/l.pngbin0 -> 669 bytes
-rw-r--r--reporting/images/logo-small.pngbin0 -> 2830 bytes
-rw-r--r--reporting/templates/clean.tmpl19
-rw-r--r--reporting/templates/foot.tmpl20
-rw-r--r--reporting/templates/head.tmpl26
-rw-r--r--reporting/templates/index.tmpl128
-rw-r--r--reporting/templates/lintian.css.tmpl447
-rw-r--r--reporting/templates/maintainer.tmpl196
-rw-r--r--reporting/templates/maintainers.tmpl57
-rw-r--r--reporting/templates/packages.tmpl35
-rw-r--r--reporting/templates/tag-not-seen.tmpl16
-rw-r--r--reporting/templates/tag.tmpl102
-rw-r--r--reporting/templates/tags-all.tmpl28
-rw-r--r--reporting/templates/tags-severity.tmpl37
-rw-r--r--reporting/templates/tags.tmpl34
20 files changed, 1319 insertions, 0 deletions
diff --git a/reporting/checkout-release b/reporting/checkout-release
new file mode 100755
index 0000000..000f363
--- /dev/null
+++ b/reporting/checkout-release
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Copyright (C) 2008 Frank Lichtenheld <djpig@debian.org>, if at all copyrightable
+# Copyright (C) 2009 Russ Allbery <rra@debian.org>
+
+# Helper script for updating lintian.debian.org to the latest lintian release
+# Call with the release number as only argument, e.g.
+#
+# $ cd /org/lintian.debian.org && ./root/reporting/checkout-release 1.25.0
+
+set -e
+
+if [ $# -ne 1 ]; then
+ echo "Usage: checkout-release <version-number>"
+ exit 2
+fi
+release=$1
+
+set -x
+
+cd root
+git fetch
+git merge "$release"
+perl -i -pe "s/(LINTIAN_VERSION = )\S+/$1\"$release\";/" root/frontend/lintian
+debian/rules build
+
+# Local Variables:
+# indent-tabs-mode: nil
+# End:
+# vim: syntax=sh sw=4 sts=4 sr et
diff --git a/reporting/config.yaml b/reporting/config.yaml
new file mode 100644
index 0000000..e3f0ecd
--- /dev/null
+++ b/reporting/config.yaml
@@ -0,0 +1,72 @@
+## Used to define some reused variables
+defaults:
+ architectures: &ARCH
+ - i386
+ - amd64
+ components: &COMP
+ - main
+ - contrib
+ - non-free
+
+## List of archives to process
+archives:
+ ## A name given to the archive
+ debian:
+ ## Name of the tracefile to use to determine how up to date
+ ## the archive is.
+ tracefile: ftp-master.debian.org
+ ## Where the archive is placed on the file system
+ base-dir: /srv/mirrors/debian
+ ## Architectures to process
+ architectures: *ARCH
+ ## Which components to process
+ components: *COMP
+ ## Which suites/distributions to process
+ distributions:
+ - unstable
+ - experimental
+ debian-debug:
+ tracefile: ftp-master.debian.org
+ base-dir: /srv/mirrors/debian-debug
+ architectures: *ARCH
+ components: *COMP
+ distributions:
+ - unstable-debug
+ - experimental-debug
+
+storage:
+## Path to the log files
+ log-dir: /srv/lintian.debian.org/logs
+## Path to a directory to hold temporary data used by lintian.
+## Used as TMPDIR for lintian and will also hold temporary labs
+## - Can be /var/tmp or /tmp as long as they have space enough
+## - Can be cleaned automatically. Either on boot or via a
+## "delete anything older than X days"-mechanism
+ scratch-space: /srv/lintian.debian.org/scratch
+## Path to a directory to hold cached data like which packages
+## have been processed.
+## - Can be in /var/cache
+## - Can be deleted to reset / restart processing from scratch
+ state-cache: /srv/lintian.debian.org/harness-state
+## Where to store latest completed report / static website
+ reports-dir: /srv/lintian.debian.org/reports-directory/www
+## Directory to use for compiling new reports
+## FIXME: This should just be a tmpdir
+ reports-work-dir: /srv/lintian.debian.org/reports-directory/www.tmp
+## Where to store collected data / historical data (used for
+## generating graphs etc.)
+ historical-data-dir: /srv/lintian.debian.org/history
+
+lintian:
+## Extra options to pass to lintian (not all options can be
+## passed via this. E.g. --cfg is ignored).
+# extra-options: ['--jobs', '2']
+
+## All of these variables will be available for templates to consume
+## via "$config_vars{VAR}"
+template-variables:
+ LINTIAN_SOURCE: https://salsa.debian.org/git/lintian/lintian.git
+
+## Source packages to not process
+blacklist:
+- gcc-8-cross-ports # #890873
diff --git a/reporting/graphs/statistics.gpi b/reporting/graphs/statistics.gpi
new file mode 100644
index 0000000..7e59a21
--- /dev/null
+++ b/reporting/graphs/statistics.gpi
@@ -0,0 +1,38 @@
+# set terminal png truecolor small size 600,300
+set terminal svg size 640,375 font "Sans,11"
+
+set style line 10 linetype 1 linecolor rgb "#FF6700" lw 1.5
+set style line 11 linetype 1 linecolor rgb "#FFEB44" lw 1.5
+set style line 12 linetype 1 linecolor rgb "#C7EA3C" lw 1.5
+set style line 13 linetype 1 linecolor rgb "#E7F6AC" lw 1.5
+set style line 14 linetype 1 linecolor rgb "#EE99EE" lw 1.5
+set style line 15 linetype 1 linecolor rgb "#CCCCCC" lw 1.5
+
+set key outside
+
+set xdata time
+set timefmt "%s"
+set format x "%b/%y"
+
+set size 1.0,0.80
+set origin 0.0,0.05
+
+set nomxtics
+set xtics nomirror scale 0.5,0 rotate by 55 offset -3.2,-2.7
+set ytics nomirror scale 0.5,0
+set offsets 0,0,500,0
+
+load "common.gpi"
+
+set xrange [ date_min : date_max ]
+set yrange [ 0 : ]
+
+set output sprintf("%s/statistics.svg", graph_dir)
+plot sprintf("%s/statistics.dat", history_dir) \
+ u 1:7 w l ls 10 t 'Errors', \
+ '' u 1:8 w l ls 11 t 'Warnings', \
+ '' u 1:9 w l ls 12 t 'Info', \
+ '' u 1:11 w l ls 13 t 'Pedantic', \
+ '' u 1:10 w l ls 14 t 'Experimental', \
+ '' u 1:12 w l ls 15 t 'Overridden'
+
diff --git a/reporting/graphs/tags.gpi b/reporting/graphs/tags.gpi
new file mode 100644
index 0000000..16ef73c
--- /dev/null
+++ b/reporting/graphs/tags.gpi
@@ -0,0 +1,35 @@
+tag=sprintf("%s", ARG1)
+# set terminal png truecolor small size 600,300
+set terminal svg size 640,375 font "Sans,11"
+
+set style fill solid 0.25
+
+set style line 20 linetype 1 linecolor rgb "#1A77C9"
+set style line 21 linetype 1 linecolor rgb "#83CDBE"
+set style line 22 linetype 1 linecolor rgb "#BBBBBB"
+
+set key outside
+
+set xdata time
+set timefmt "%s"
+set format x "%b/%y"
+
+set size 1.0,0.80
+set origin 0.0,0.05
+
+set nomxtics
+set xtics nomirror scale 0.5,0 rotate by 55 offset -3.2,-2.7
+set ytics nomirror scale 0.5,0
+set offsets 0,0,1,0
+
+load "common.gpi"
+
+set xrange [ date_min : date_max ]
+set yrange [ 0 : ]
+
+set output sprintf("%s/tags/%s.svg", graph_dir, tag)
+plot sprintf("%s/tags/%s.dat", history_dir, tag) \
+ u 1:2 w filledcurve x1 ls 20 t sprintf("Tag %s emitted", tag), \
+ '' u 1:4 w filledcurve x1 ls 21 t sprintf("Packages which emitted %s", tag), \
+ '' u 1:3 w filledcurve x1 ls 22 t sprintf("Tag %s overridden", tag)
+
diff --git a/reporting/images/ico.png b/reporting/images/ico.png
new file mode 100644
index 0000000..e78bd5b
--- /dev/null
+++ b/reporting/images/ico.png
Binary files differ
diff --git a/reporting/images/l.png b/reporting/images/l.png
new file mode 100644
index 0000000..0473ba2
--- /dev/null
+++ b/reporting/images/l.png
Binary files differ
diff --git a/reporting/images/logo-small.png b/reporting/images/logo-small.png
new file mode 100644
index 0000000..59bf0c7
--- /dev/null
+++ b/reporting/images/logo-small.png
Binary files differ
diff --git a/reporting/templates/clean.tmpl b/reporting/templates/clean.tmpl
new file mode 100644
index 0000000..5ae636a
--- /dev/null
+++ b/reporting/templates/clean.tmpl
@@ -0,0 +1,19 @@
+{ head("Lintian Report for $name", 1) }
+ <h1>{$name}</h1>
+
+ <p>
+ All of the packages maintained by {$maintainer} are Lintian-clean.
+{
+ if (!$clean) {
+ qq( But also see the <a href="${path_prefix}full/$id">full report</a>)
+ . " which includes info, experimental and overridden tags";
+ }
+}
+ </p>
+
+ <p>
+ Also see their
+ <a href="https://qa.debian.org/developer.php?login={$email}">QA
+ overview</a>.
+ </p>
+{ foot() }
diff --git a/reporting/templates/foot.tmpl b/reporting/templates/foot.tmpl
new file mode 100644
index 0000000..ddc7dc1
--- /dev/null
+++ b/reporting/templates/foot.tmpl
@@ -0,0 +1,20 @@
+</main>
+
+<hr/>
+
+<footer>
+ <p>
+ Comments about these web pages? Please use
+ <a href="https://packages.debian.org/sid/reportbug">reportbug</a>
+ to report a bug against the lintian package.
+ </p>
+ <p>
+ The source code to Lintian is available under the GNU GPL version 2,
+ or (at your option) any later version. It can be downloaded from
+ <a href="{$config_vars{LINTIAN_SOURCE}}">{$config_vars{LINTIAN_SOURCE}}</a>.
+ </p>
+ <p>Page last updated: {$timestamp} using Lintian {$version}.</p>
+</footer>
+
+</body>
+</html>
diff --git a/reporting/templates/head.tmpl b/reporting/templates/head.tmpl
new file mode 100644
index 0000000..4001950
--- /dev/null
+++ b/reporting/templates/head.tmpl
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>{$page_title}</title>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ <link rel="stylesheet" href="{resource_path('lintian.css')}" type="text/css" integrity="{resource_integrity('lintian.css')}" crossorigin="anonymous" />
+ <link rel="icon" href="{resource_path('ico.png')}" type="image/png" integrity="{resource_integrity('ico.png')}" crossorigin="anonymous" />
+</head>
+
+<body>
+
+<header>
+ <p><a href="{$path_prefix}index.html">Lintian Reports</a></p>
+ <nav>
+ <ul id="nav">
+ <li><a href="{$path_prefix}maintainers.html">Maintainers</a></li>
+ <li><a href="{$path_prefix}tags.html">Emitted Tags</a></li>
+ <li><a href="{$path_prefix}tags-all.html">All Tags</a></li>
+ <li><a href="{$path_prefix}packages_1.html">Packages</a></li>
+ </ul>
+ </nav>
+ <div class="clear"></div>
+</header>
+
+<main>
diff --git a/reporting/templates/index.tmpl b/reporting/templates/index.tmpl
new file mode 100644
index 0000000..0889624
--- /dev/null
+++ b/reporting/templates/index.tmpl
@@ -0,0 +1,128 @@
+{ head("Lintian") }
+ <div id="front">
+ <div id="info">
+ <p>
+ Lintian dissects <a href="https://www.debian.org/">Debian</a>
+ <a href="https://packages.debian.org/">packages</a> and tries to find
+ bugs and policy violations. It contains automated checks for many
+ aspects of <a href="https://www.debian.org/doc/debian-policy/">Debian
+ policy</a> as well as some checks for common errors.
+ </p>
+
+ <p>
+ For more information, see the <a href="{$path_prefix}manual/index.html">User
+ Manual</a>.
+ </p>
+
+ <p>
+ Auto-generated documentation of the Lintian Perl Library API can
+ be found <a href="{$path_prefix}library-api/index.html">here</a>.
+ </p>
+
+
+ <p>
+ Lintian is available in the Debian
+ <a href="https://packages.debian.org/lintian">lintian package</a>.
+ </p>
+ </div> <!-- info -->
+ <div class="clear"></div>
+ </div> <!-- front -->
+
+ <nav id="index">
+ <h2>Indices and links</h2>
+
+ <ul>
+ <li><a href="{$path_prefix}maintainers.html">Index of Lintian reports per package maintainers</a></li>
+ <li><a href="{$path_prefix}tags.html">List of emitted tags sorted alphabetically</a></li>
+ <li><a href="{$path_prefix}tags-severity.html">List of emitted tags grouped by severity</a></li>
+ <li><a href="{$path_prefix}tags-all.html">List of all tags sorted alphabetically</a></li>
+ <li>Lists of packages that have names starting with:
+ <ul>
+ <li><a href="{$path_prefix}packages_1.html">0-9, A-F</a></li>
+ <li><a href="{$path_prefix}packages_2.html">G-L</a></li>
+ <li><a href="{$path_prefix}packages_3.html">M-R</a></li>
+ <li><a href="{$path_prefix}packages_4.html">S-Z</a></li>
+ </ul>
+ </li>
+ <li>Download the lintian output for off-line processing: <a href="{resource_path('lintian.log.gz')}">lintian.log.gz</a></li>
+ </ul>
+ </nav> <!-- index -->
+
+ <div id="archives">
+ <h2>Archives</h2>
+ <p>The following archives are processed by Lintian:</p>
+ <table>
+ <tr><th>Archive name</th><th>Attribute</th><th>Attribute value</th></tr>
+{
+ for my $archive_info (@archives) {
+ my $name = $archive_info->{'name'};
+ my $archs = join(' ', @{$archive_info->{'architectures'}});
+ my $distributions = join(' ', @{$archive_info->{'distributions'}});
+ my $components = join(' ', @{$archive_info->{'components'}});
+ my $timestamp = $archive_info->{'timestamp'};
+ $OUT .= qq{ <tr><td rowspan="4">${name}</td><td>Architectures</td><td>$archs</td></tr>\n};
+ $OUT .= qq{ <tr><td>Distributions/Suites</td><td>$distributions</td></tr>\n};
+ $OUT .= qq{ <tr><td>Components</td><td>$components</td></tr>\n};
+ $OUT .= qq{ <tr><td>Mirror timestamp</td><td>$timestamp</td></tr>\n};
+ }
+}
+ </table>
+ </div>
+
+ <div id="stats">
+ <h2>Statistics</h2>
+ <table>
+ <tr><td>Last updated:</td> <td>{$timestamp}</td></tr>
+ <tr><td>Maintainers:</td> <td>{$delta{maintainers}}</td></tr>
+ <tr><td>Package groups:</td> <td>{$delta{'groups-known'}}</td></tr>
+ <tr><td>Rescheduled groups:</td> <td>{$delta{'groups-backlog'}}</td></tr>
+ <tr><td>Groups with processing errors:</td> <td>{$delta{'groups-with-errors'}}</td></tr>
+ <tr><td>Source packages:</td> <td>{$delta{'source-packages'}}</td></tr>
+ <tr><td>Binary packages:</td> <td>{$delta{'binary-packages'}}</td></tr>
+ <tr><td>&mu;deb packages:</td> <td>{$delta{'udeb-packages'}}</td></tr>
+ <tr>
+ <td><span class="type-E">E</span> Errors:</td>
+ <td>{$delta{errors}}</td>
+ </tr>
+ <tr>
+ <td><span class="type-W">W</span> Warnings:</td>
+ <td>{$delta{warnings}}</td>
+ </tr>
+ <tr>
+ <td><span class="type-I">I</span> Info tags:</td>
+ <td>{$delta{info}}</td>
+ </tr>
+ <tr>
+ <td><span class="type-P">P</span> Pedantic tags:</td>
+ <td>{$delta{pedantic}}</td>
+ </tr>
+ <tr>
+ <td><span class="type-O">O</span> Overridden tags:</td>
+ <td>{$delta{overridden}}</td>
+ </tr>
+ <tr>
+ <td><span class="type-X">X</span> Experimental tags:</td>
+ <td>{$delta{experimental}}</td>
+ </tr>
+ <tr><td>Lintian version:</td> <td>{$version}</td></tr>
+ </table>
+
+ <p>
+ (The numbers in parentheses describe the changes since the last Lintian
+ report, published on {$previous}.)
+ </p>
+
+{
+ if ($graphs) {
+ my $graph_link = resource_path('statistics.svg');
+ $OUT .= qq( <p>\n);
+ $OUT .= qq( Evolution of Lintian tags over the past\n);
+ $OUT .= qq( $graphs_days days:</p>\n);
+ $OUT .= qq( <div class="graph"><a href="${graph_link}"><img class="graph"\n);
+ $OUT .= qq( src="${graph_link}" alt="The beforementioned graph of Lintian\n);
+ $OUT .= qq( tags" /></a></div>\n);
+ }
+}
+
+ </div> <!-- stats -->
+{ foot() }
diff --git a/reporting/templates/lintian.css.tmpl b/reporting/templates/lintian.css.tmpl
new file mode 100644
index 0000000..cc3e8a3
--- /dev/null
+++ b/reporting/templates/lintian.css.tmpl
@@ -0,0 +1,447 @@
+{{{
+ # NOTE - in this file, perl code must be within three braces rather than
+ # the usual single brace. This was done because a single brace is rather
+ # common in .css-files. NB: The braces cannot be escaped - see "DELIMITERS"
+ # in Text::Template.
+ #
+ # To refer to a resource, use:
+ # {{{resource_path('basename.png')}}}
+ # NB: The path will be relative to the .css file. Usually something like
+ # "../resources/<checksum>.png"
+ #
+ # To refer to a file name relative to the .css file, use:
+ # {{{$path_prefix}}}path/from/HTML_ROOT
+}}}/* lintian.css -- Style sheet for lintian.debian.org pages. */
+
+/*
+ # Table of Contents:
+ #
+ # 1. General styles (links, lists, titles, tables...)
+ # 2. Header
+ # 3. Navigation
+ # 4. Main content
+ # 5. Footer
+ # 6. Other
+ */
+
+/*
+ # Order:
+ #
+ # example {
+ # display
+ # position
+ # width
+ # height
+ # margin
+ # padding
+ # background
+ # color
+ # font
+ # text
+ # line-height
+ # border
+ # }
+ */
+
+
+/*
+ * 1. General styles
+ */
+
+body {
+ margin: 0;
+ padding: 0;
+ color: #222;
+ background-color: white;
+ font-family: sans-serif;
+}
+
+h1, h2 {
+ font-family: "Junicode", "FreeSerif", serif;
+}
+
+h2 {
+ margin-bottom: 14px;
+ padding-bottom: 6px;
+ border-bottom: 2px solid #AAA;
+}
+
+h3 {
+ margin: 5px 0 5px 10px;
+ color: #444;
+ font-size: 1.0em;
+}
+
+p {
+ line-height: 1.4em;
+}
+
+a {
+ color: #3252B2;
+}
+
+ul {
+ margin: 0;
+}
+
+li {
+ color: #333;
+}
+
+hr {
+ display: none;
+}
+
+/*
+ * 2. Header title
+ */
+
+header {
+ display: block; /* HTML5 compat */
+ margin: 0 0 28px 0;
+ padding: 5px 20px;
+ background: #F3F3F3 url("{{{resource_path('logo-small.png')}}}") no-repeat right;
+ border-bottom: 1px solid #AAA;
+}
+
+header p {
+ float: left;
+ margin: 5px 0;
+ color: #444;
+ font-size: 1.0em;
+ font-family: sans-serif;
+ font-weight: bold;
+}
+
+header p a {
+ color: #444;
+ text-decoration: none;
+}
+
+
+/*
+ * 3. Navigation bar
+ */
+
+#nav {
+ float: right;
+ margin: 5px 55px 5px 0;
+ padding: 0;
+}
+
+#nav li {
+ display: inline;
+ margin-left: 5px;
+}
+
+#nav a {
+ padding: 3px 5px;
+ color: #333;
+ font-size: 0.9em;
+ text-decoration: none;
+}
+
+#nav a:hover {
+ background-color: #FBFBFB;
+ border-bottom: 2px solid #D70751;
+}
+
+
+/*
+ * 4. Main content
+ */
+
+main {
+ display: block;
+ margin: 0 25px;
+ font-size: 0.9em;
+ line-height: 1.4em;
+}
+
+img.graph {
+ width: 95%;
+ max-width: 640px;
+}
+
+/* Front page */
+
+#logo {
+ text-align: center;
+}
+
+#index h2, #stats h2, #archives h2 {
+ margin: 1.4em 0 0.4em 0;
+ border: none;
+}
+
+#info {
+ margin: 25px 0;
+ padding: 20px;
+ background: #EFF4F8 url("{{{resource_path('l.png')}}}") no-repeat left;
+ border: 1px solid #DFE4E8;
+}
+
+#info p {
+ margin-left: 130px;
+}
+
+/* For smaller devices, we leave out the "icon" - it is fairly wide with
+ * little added value.
+ */
+@media (max-width: 700px) {
+
+ #info {
+ margin: 25px 0;
+ padding: 20px;
+ background: #EFF4F8;
+ border: 1px solid #DFE4E8;
+ }
+
+ #info p {
+ margin-left: 5%;
+ }
+}
+
+#stats table, #archives table {
+ border-collapse: collapse;
+}
+
+#stats table tr td, #archives table tr td {
+ padding: 3px 5px;
+ background-color: #FDFDFD;
+ border: 1px solid #CCC;
+}
+
+#stats td span, #archives td span {
+ margin: 0 3px 0 0;
+ padding: 1px 3px;
+ font-family: monospace;
+}
+
+#stats div.graph {
+ text-align: left;
+}
+
+/* Maintainer reports */
+
+#summary {
+ font-size: 0.9em;
+}
+
+#summary p {
+ margin-top: 5px;
+ font-size: 0.95em;
+}
+
+#summary ul {
+ padding-left: 20px;
+}
+
+ul.report {
+ padding-left: 20px;
+ padding-bottom: 1em;
+}
+
+div.graph {
+ text-align: center;
+}
+
+ul.tag {
+ padding-bottom: 1em;
+}
+
+ul.report li {
+ padding-left: 5px;
+ padding-bottom: 6px;
+ list-style: none;
+}
+
+ul.tag li {
+ list-style: square;
+}
+
+li span {
+ margin: 0 3px 0 0;
+ padding: 1px 3px;
+ font-family: monospace;
+}
+
+h1 span {
+ padding: 1px 5px;
+ font-family: monospace;
+ font-size: 0.85em;
+ font-weight: normal;
+}
+
+ul.extra {
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+
+ul.report li ul.extra li {
+ padding-left: 0;
+ padding-bottom: 1px;
+ color: #444;
+ list-style: square;
+}
+
+div.source-header {
+ width: 100%;
+ margin: 1.4em 0 14px 0;
+ padding-bottom: 6px;
+ border-bottom: 2px solid #AAA;
+}
+
+div.source-header p, div.source-header h2 {
+ display: inline;
+ border: none;
+}
+
+.info-links {
+ margin-top: 0;
+}
+
+.info-links:before {
+ content: "– ";
+}
+
+/* Tag type */
+
+h2.tag {
+ margin: 5px 0;
+ padding: 0;
+ color: #444;
+ font-family: sans-serif;
+ font-size: 1.0em;
+ font-weight: normal;
+ border: none;
+}
+
+h2.tag a {
+ font-weight: bold;
+}
+
+h2.tag span.type-O {
+ margin: 0 3px 0 0;
+ padding: 2px 4px;
+ color: #555;
+ background: #EEE;
+ font-family: monospace;
+ font-size: 1.1em;
+ font-weight: bold;
+ border: 1px solid #DDD;
+}
+
+br.tag {
+ padding-bottom: 1em;
+}
+
+
+/* E/W/I colors */
+
+span.type-I {
+ color: #111;
+ background-color: #C7EA3C;
+}
+
+span.type-W {
+ color: #111;
+ background-color: #FFEB44;
+}
+
+span.type-E {
+ color: #111;
+ background-color: #FF6700;
+}
+
+span.type-X {
+ color: #111;
+ background-color: #EE99EE;
+}
+
+span.type-O {
+ color: #111;
+ background-color: #DDD;
+}
+
+span.type-P {
+ color: #111;
+ background-color: #C7EA3C;
+}
+
+span.type-C {
+ color: #111;
+ background-color: blue;
+}
+
+li.type-O {
+ color: #444;
+}
+
+b.processing-error {
+ color: #FF6700;
+}
+
+blockquote {
+ padding: 6px 16px;
+ background-color: #EEE;
+ border: 1px solid #DDD;
+}
+
+blockquote.type-I {
+ background-color: #DFA;
+ border: 1px solid #C7EA3C;
+}
+
+blockquote.type-W {
+ background-color: #FFD;
+ border: 1px solid #FFEB44;
+}
+
+blockquote.type-E {
+ background-color: #FE9;
+ border: 1px solid #FF6700;
+}
+
+blockquote.type-X {
+ background-color: #FECCFE;
+ border: 1px solid #DE66DE;
+}
+
+blockquote.type-P {
+ background-color: #DFA;
+ border: 1px solid #C7EA3C;
+}
+
+blockquote.type-C {
+ background-color: #DFA;
+ border: 1px solid #C7EA3C;
+}
+
+
+/*
+ * 5. Footer
+ */
+
+footer {
+ display: block; /* HTML5 compat */
+ margin: 20px 20px;
+ padding: 10px 0 0 0;
+ font-size: 0.85em;
+ border-top: 1px solid #AAA;
+}
+
+footer p {
+ margin: 0;
+ padding: 0;
+}
+
+
+/*
+ * 6. Other
+ */
+
+div.clear {
+ clear: both;
+}
+
diff --git a/reporting/templates/maintainer.tmpl b/reporting/templates/maintainer.tmpl
new file mode 100644
index 0000000..e5e9353
--- /dev/null
+++ b/reporting/templates/maintainer.tmpl
@@ -0,0 +1,196 @@
+{ head("Lintian Report for $name") }
+ <h1>{$name}</h1>
+
+ <p>
+ At the time of the last Lintian run, the following possible problems
+ were found in packages maintained by {$maintainer}, listed by source
+ package.
+{
+ if ($errors) {
+ qq( See also the <a href="${path_prefix}full/$id">full report</a>, including)
+ . " info, experimental and overridden tags.";
+ } else {
+ qq( See also the <a href="${path_prefix}maintainer/$id">report showing)
+ . " only errors and warnings</a>.";
+ }
+}
+ Also see their
+ <a href="https://qa.debian.org/developer.php?login={$email}">QA
+ overview</a>.
+ </p>
+
+{
+ # Show the summary only if the number of packages is within a certain
+ # range.
+ my $num_packages = keys(%packages) + keys(%uploads);
+ if ($num_packages) {
+ $OUT .= qq( <nav id="summary">\n <ul>\n);
+ foreach my $source (sort(keys(%packages), keys(%uploads))) {
+ # Only display a link for the package if either we're
+ # displaying the full report, or the package has error
+ # or warning tags
+ my @interesting = ();
+ my $versions = $packages{$source} || $uploads{$source};
+
+ if (!$errors) {
+ # Full report, so include the package
+ @interesting = sort by_version keys %$versions;
+ @interesting = map {
+ [$_, $versions->{$_}[0]{pkg_info}{anchor}]
+ } @interesting;
+ } else {
+ for my $version (sort by_version keys %$versions) {
+ my $tags = $versions->{$version};
+ for my $tag (@$tags) {
+ if (($tag->{code} eq 'E') or ($tag->{code} eq 'W')) {
+ push(@interesting, [$version, $tag->{pkg_info}{anchor}]);
+ last;
+ }
+ }
+ }
+ }
+
+ if (@interesting) {
+ foreach my $vdata (@interesting) {
+ my ($version, $anchor) = @{$vdata};
+ $OUT .= q{ } .
+ qq(<li><a href="#${anchor}">$source ($version)</a></li>\n);
+ }
+ }
+ }
+ $OUT .= " </ul>\n </nav>\n";
+ }
+}
+ <div class="clear"></div>
+
+{
+ # We get a hash of package names to a hash of versions to a list of tags.
+ # Create a list with the package information as the title and the tags as
+ # the value.
+ for my $source (sort (keys (%packages), keys (%uploads))) {
+ my ($data, $upload);
+ my $first_version = 1;
+ if ($packages{$source}) {
+ $data = $packages{$source};
+ } else {
+ $data = $uploads{$source};
+ $upload = 1;
+ }
+ for my $version (sort by_version keys %$data) {
+ my @tags = @{$data->{$version}};
+ my @error_tags = grep { $_->{code} eq 'E' or $_->{code} eq 'W' } @tags;
+ my $first = 1;
+ my $binary = '';
+ my $tag = '';
+ my $firstcomponent = '';
+ # Tracks whether we have opened an "<ul>"-list for the tag "extra".
+ # We only do this if the tags have "extra" info to avoid an empty
+ # "<ul></ul>" (which is forbidden by XHTML 1.0 strict).
+ my $has_extra = 0;
+
+ if ($errors) {
+ @tags = @error_tags;
+ next if not @error_tags;
+ }
+
+ for my $info (@tags) {
+ my $pkg_info = $info->{pkg_info};
+ my $is_binary = ($pkg_info->{type} eq "binary" or $pkg_info->{type} eq "udeb");
+ my $new_binary = $pkg_info->{package} ne $binary if $is_binary;
+ my $tag_info = $info->{tag_info};
+ my $next_tag = $tag_info->name;
+
+ my $component = ($pkg_info->{component} eq 'main') ? '' : "; $pkg_info->{component}";
+ $firstcomponent = $pkg_info->{component} unless $firstcomponent;
+ if ($first) {
+ my $state = $pkg_info->{'state_data'};
+ my $anchor = $pkg_info->{'anchor'};
+ my $status = 'up-to-date';
+ my $last_processed_by = $state->{'last-processed-by'} // 'N/A';
+ $status = '<i>outdated</i>' if (exists($state->{'out-of-date'}));
+ $status = '<b class="processing-error">incomplete report; an error occurred during the last check</b>'
+ if exists($state->{'last-error-by'}) and $state->{'last-error-by'};
+ $OUT .= qq( <div class="source-header">\n);
+ $OUT .= qq( <h2 id="$pkg_info->{anchor}">);
+ $OUT .= "$source ($version$component)";
+ $OUT .= " [Uploader]" if $upload;
+ if ($first_version) {
+ # Unversioned #<pkg> references just go to the first version.
+ $first_version = 0;
+ $OUT .= qq( <a href="#${source}" id="${source}">&sect;</a>)
+ }
+ $OUT .= "</h2>\n";
+ $OUT .= qq( <p class="info-links">\n);
+ $OUT .= qq( <a href="https://packages.debian.org/src:$source">Info</a>\n);
+ $OUT .= qq( <a href="https://tracker.debian.org/$source">Package Tracker</a>\n);
+ $OUT .= qq( <a href="https://bugs.debian.org/src:$source">Bugs</a>\n);
+ $OUT .= qq( <a href="https://sources.debian.org/src/$source/$version">Source</a>\n);
+ if ($errors) {
+ $OUT .= qq( <a href="${path_prefix}full/$id#$anchor">Full report</a>\n);
+ } elsif (@error_tags) {
+ $OUT .= qq( <a href="${path_prefix}maintainer/$id#$anchor">Short report</a>\n);
+ }
+ $OUT .= qq[ (${status}, last processed by Lintian/$last_processed_by)];
+ $OUT .= qq( </p>\n </div>\n);
+ $OUT .= qq( <ul class="report">\n) unless $is_binary;
+ }
+
+ my $bin_version = '';
+ unless ($pkg_info->{version} eq $version
+ and $pkg_info->{component} eq $firstcomponent) {
+ $bin_version = " ($pkg_info->{version}; $pkg_info->{component})";
+ }
+
+ if ($tag ne $next_tag or $new_binary) {
+ # Close the '<ul class="extra">' HTML tag if it is open
+ $OUT .= "</ul>\n" if $has_extra;
+ # Reset has_extra; if the tag has an "extra", we will check
+ # for it later.
+ $has_extra = 0;
+ if ($new_binary) {
+ $OUT .= " </li>\n </ul>\n" unless $first;
+ $OUT .= qq( <h3>$pkg_info->{package}$bin_version</h3>\n);
+ $OUT .= qq( <ul class="report">\n);
+ }
+ }
+
+ my $class = '';
+ # No HTML quote needed; severity is from a fixed
+ # whitelist of known safe words.
+ my $severity = $tag_info->effective_severity;
+ $class = qq( title="$severity");
+
+ # Display tag name only once.
+ if ($tag ne $next_tag or $new_binary) {
+ my $q_next_tag = html_quote($next_tag);
+ $OUT .= " </li>\n" unless $first or $new_binary;
+ $OUT .= " <li$class>\n";
+ $OUT .= qq( <span class="type-$info->{code}">);
+ $OUT .= "$info->{code}</span> ";
+ $OUT .= qq(<a href="${path_prefix}tags/${q_next_tag}.html">);
+ $OUT .= "${q_next_tag}</a>\n";
+ }
+
+ if ($info->{extra}) {
+ if (not $has_extra) {
+ # Open a list for the "extra" info.
+ $has_extra = 1;
+ $OUT .= qq( <ul class="extra">);
+ }
+ $OUT .= "<li>$info->{extra}";
+ my @archs = sort keys %{ $info->{archs} };
+ $OUT .= " <tt>[" . join(', ', @archs) . "]</tt>" if @archs > 1;
+ $OUT .= "</li>";
+ }
+
+ $first = 0;
+ $binary = $pkg_info->{package} if $is_binary;
+ $tag = $next_tag;
+ }
+ # Close the "extra" info-list (if present) and the current setup
+ $OUT .= "</ul>\n" if $has_extra;
+ $OUT .= " </li>\n </ul>\n";
+ }
+ }
+}
+{ foot() }
diff --git a/reporting/templates/maintainers.tmpl b/reporting/templates/maintainers.tmpl
new file mode 100644
index 0000000..58a9626
--- /dev/null
+++ b/reporting/templates/maintainers.tmpl
@@ -0,0 +1,57 @@
+{ head("Lintian Reports by Maintainer") }
+ <h1>Maintainers</h1>
+
+ <p>
+ Maintainers are listed sorted case-insensitively by package maintainer
+ string. This is an unsophisticated sort that does not take into
+ account any national collating sequence, only Unicode strings, so
+ maintainers whose names start with non-ASCII characters will sort at
+ the end of this page.
+ </p>
+
+ <p>
+ Jump to: { join (' ', (map { qq(<a href="#$_">$_</a>) } 'A'..'Z', 'Other')) }
+{
+ # !!NB!! We are deliberately leaving out the closing "</p>" here.
+ # It will be added by the loop below, which can (due to this)
+ # unconditionally emit a "</p>" at the start of each new letter.
+
+ # Put headings before each new initial letter and add anchors, except
+ # for non-ASCII initial characters. For those, since we can't be
+ # assured we'll get combining characters right, just accumulate them
+ # under a heading of Other.
+ my $letter = '';
+ my @order = sort {
+ my $la = lc($a);
+ my $lb = lc($b);
+ # Ensure non-ASCII characters get push to the back
+ if ($la lt 'a' and $lb ge 'a') {
+ 1;
+ } elsif ($la ge 'a' and $lb lt 'a') {
+ -1;
+ } else {
+ $la cmp $lb;
+ }
+ } keys(%maintainers);
+ for my $key (@order) {
+ my $maint_data = $maintainers{$key};
+ my $url = $maint_data->{url};
+ my $maintainer = $maint_data->{name};
+ my $first = uc substr($key, 0, 1);
+ if ($first lt 'A' || $first gt 'Z') {
+ $first = 'Other';
+ }
+ if ($first ne $letter) {
+ $letter = $first;
+ if ($letter eq 'Other') {
+ $OUT .= qq( </p>\n\n <h2 id="Other">Other</h2>\n\n <p>\n);
+ } else {
+ $OUT .= qq( </p>\n\n <h2 id="$letter"><a id="$letter">)
+ . $letter . "</a></h2>\n\n <p>\n";
+ }
+ }
+ $OUT .= qq( <a href="${path_prefix}maintainer/$url">$maintainer</a>)
+ . qq{ (<a href="${path_prefix}full/$url">full report</a>)<br />\n};
+ }
+} </p>
+{ foot() }
diff --git a/reporting/templates/packages.tmpl b/reporting/templates/packages.tmpl
new file mode 100644
index 0000000..352f6b1
--- /dev/null
+++ b/reporting/templates/packages.tmpl
@@ -0,0 +1,35 @@
+{ head("Lintian Package Index: $section") }
+ <h1>Package Index: {$section}</h1>
+
+ <p>
+ This is a list of all source packages that have at least one
+ lintian tag. This includes all tags, even experimental and info tags
+ and tags that were overridden. The list is huge, so it's broken into
+ four separate pages. This page covers package names starting with
+ {$section}.
+ </p>
+
+ <p>
+ <a href="{$path_prefix}packages_1.html">0-9, A-F</a>
+ | <a href="{$path_prefix}packages_2.html">G-L</a>
+ | <a href="{$path_prefix}packages_3.html">M-R</a>
+ | <a href="{$path_prefix}packages_4.html">S-Z</a>
+ </p>
+
+{
+ # ' # hi, emacs
+ # Put headings before each new initial letter.
+ my $letter = '';
+ for my $package (@list) {
+ my $first = uc substr($package, 0, 1);
+ if ($first ne $letter) {
+ $OUT .= " </p>\n\n" if $letter;
+ $OUT .= qq( <h2>$first</h2>\n\n <p>\n);
+ $letter = $first;
+ }
+ foreach my $version (sort by_version keys %{ $sources{$package} }) {
+ $OUT .= qq( <a href="${path_prefix}full/$sources{$package}{$version}">$package ($version)</a>\n);
+ }
+ }
+} </p>
+{ foot() }
diff --git a/reporting/templates/tag-not-seen.tmpl b/reporting/templates/tag-not-seen.tmpl
new file mode 100644
index 0000000..2e3c8a9
--- /dev/null
+++ b/reporting/templates/tag-not-seen.tmpl
@@ -0,0 +1,16 @@
+{ head("Lintian Tag: $tag") }
+ <h1><span class="type-{$code}">{$code}</span> {$tag}</h1>
+
+ <p>
+ All reports of {$tag} for the archive. The extended description of this
+ tag is:
+ </p>
+
+ <blockquote class="type-{$code}">
+{$description}
+ </blockquote>
+
+ <p>
+ This tag has not been emitted in any package tested by Lintian.
+ </p>
+{ foot() }
diff --git a/reporting/templates/tag.tmpl b/reporting/templates/tag.tmpl
new file mode 100644
index 0000000..d7c7271
--- /dev/null
+++ b/reporting/templates/tag.tmpl
@@ -0,0 +1,102 @@
+{ # No my/our in front of $q_tag or it will leave scope too soon!
+ $q_tag = html_quote($tag);
+ head("Lintian Tag: ${q_tag}") }
+ <h1><span class="type-{$code}">{$code}</span> {${q_tag}}</h1>
+
+{ if ($statistics{total} <= $shown_count) {
+ $OUT .= qq(
+ <p>
+ All reports of ${tag} for the archive. The extended description of this
+ tag is:
+ </p>
+);
+ } else {
+ my $log_link = resource_path('lintian.log.gz');
+ $OUT .= qq(
+ <p>
+ A subset of the reports of ${tag} for the archive. Unfortunately the full
+ list is too long, so only ${shown_count} instances are listed on this page.
+ At most ${tag_limit_per_package} tags are shown per package.
+ <a href="${log_link}">If you need the full list of tags,
+ please download the lintian.log.gz file and extract the data you need.</a>
+ </p>
+ <p>
+ The extended description of this tag is:
+ </p>
+ );
+ }
+}
+
+ <blockquote class="type-{$code}">
+{$description}
+ </blockquote>
+
+{
+ if ($graphs) {
+ my $graph_link = resource_path("${tag}.svg");
+ $OUT .= qq( <p>\n);
+ $OUT .= qq( Evolution of the ${q_tag} Lintian tag over the past\n);
+ $OUT .= qq( $graphs_days days:</p>\n);
+ $OUT .= qq( <div class="graph"><a href="${graph_link}"><img class="graph"\n);
+ $OUT .= qq( src="${graph_link}" alt="The beforementioned graph for the ${q_tag} tag"\n);
+ $OUT .= qq( /></a></div>\n);
+ }
+ $OUT .= qq(<p>Emitted (non-overridden): $statistics{count}, );
+ $OUT .= qq(overridden: $statistics{overrides}, );
+ $OUT .= qq(total: $statistics{total}</p>);
+}
+
+ <p>
+ The package names link to the relevant maintainer page and the
+ corresponding report for the source package. The links go to the full
+ maintainer report page, which includes info and experimental tags and
+ overridden tags, rather than the default page that shows only errors
+ and warnings.
+ </p>
+{
+ # We get a list of tag data. We create a separate paragraph for each
+ # package name.
+ my ($last, $last_pi, $tag, $has_nonoverridden);
+ for my $info (sort { $a->{pkg_info}{package} cmp $b->{pkg_info}{package} } @tags) {
+ my $pkg_info = $info->{pkg_info};
+ if (!$last
+ or "$pkg_info->{package} $pkg_info->{type} $pkg_info->{version}" ne "$last_pi->{package} $last_pi->{type} $last_pi->{version}") {
+ if ($last) {
+ my $overridden = $has_nonoverridden ? '' : qq{ <span class="type-O">overridden</span>};
+ $OUT .= qq( <h2 class="tag"><a href="${path_prefix}full/$last->{pkg_info}{xref}">);
+ $OUT .= "$last_pi->{package} $last_pi->{version}</a> ($last_pi->{type}) (<em>$last_pi->{maintainer}</em>)$overridden</em></h2>\n";
+ if ($tag) {
+ $OUT .= qq( <ul class="tag">\n);
+ $OUT .= $tag;
+ $OUT .= "</ul>\n";
+ } else {
+ $OUT .= qq(<br class="tag" />\n);
+ }
+ }
+ $last = $info;
+ $last_pi = $pkg_info;
+ $tag = '';
+ $has_nonoverridden = 0;
+ }
+ $has_nonoverridden = 1 if $info->{code} ne 'O';
+ if ($info->{extra}) {
+ $tag .= qq{ <li class="type-$info->{code}">};
+ $tag .= qq{<span class="type-O">O</span> } if $info->{code} eq 'O';
+ $tag .= $info->{extra};
+ my @archs = sort keys %{ $info->{archs} };
+ $tag .= " <tt>[" . join(', ', @archs) . "]</tt>" if @archs > 1;
+ $tag .= "</li>";
+ }
+ }
+ my $overridden = $has_nonoverridden ? '' : qq{ <span class="type-O">overridden</span>};
+ $OUT .= qq( <h2 class="tag"><a href="${path_prefix}full/$last->{pkg_info}{xref}">);
+ $OUT .= "$last_pi->{package} $last_pi->{version}</a> ($last_pi->{type}) (<em>$last_pi->{maintainer}</em>)$overridden</h2>\n";
+ if ($tag) {
+ $OUT .= qq( <ul class="tag">\n);
+ $OUT .= $tag;
+ $OUT .= "</ul>\n";
+ } else {
+ $OUT .= qq(<br class="tag" />\n);
+ }
+}
+{ foot() }
diff --git a/reporting/templates/tags-all.tmpl b/reporting/templates/tags-all.tmpl
new file mode 100644
index 0000000..eb592c3
--- /dev/null
+++ b/reporting/templates/tags-all.tmpl
@@ -0,0 +1,28 @@
+{ head("Lintian Tags") }
+ <h1>Tags</h1>
+
+ <p>
+ This is a list of all tags known to Lintian even the ones
+ not emitted.
+ </p>
+
+ <ul>
+{
+ for my $tag (sort $profile->known_tags) {
+ my $text;
+ my $q_tag = html_quote($tag);
+ if ($stats{$tag}) {
+ my $packages = $stats{$tag}{'packages'};
+ my $count = $stats{$tag}{'count'};
+ my $overrides = $stats{$tag}{'overrides'};
+ $text = "$packages packages, $count tags"
+ . ($overrides > 0 ? ", plus $overrides overrides" : "");
+ } else {
+ $text = 'Not emitted';
+ }
+ $OUT .= qq( <li><a href="${path_prefix}tags/${q_tag}.html">${q_tag}</a>)
+ . " ($text)"
+ . "</li>\n";
+ }
+} </ul>
+{ foot() }
diff --git a/reporting/templates/tags-severity.tmpl b/reporting/templates/tags-severity.tmpl
new file mode 100644
index 0000000..164cb40
--- /dev/null
+++ b/reporting/templates/tags-severity.tmpl
@@ -0,0 +1,37 @@
+{ head("Lintian Tags") }
+ <h1>Tags</h1>
+
+ <p>
+ This is a list of all tags that occur at least once in the archive
+ sorted by severity. This includes all tags, even experimental and
+ info tags.
+ </p>
+
+{
+ my @tags = sort keys %tags;
+ for my $severity (qw/error warning info pedantic classification/) {
+ my $heading = 0;
+ for my $tag (@tags) {
+ my ($first) = @{ $tags{$tag} };
+ my $tag_info = $first->{tag_info};
+ next unless $tag_info->effective_severity eq $severity;
+ unless ($heading) {
+ $OUT .= " <h2>Severity: $severity,";
+ $OUT .= " <ul>\n";
+ $heading = 1;
+ }
+ my $packages = $stats{$tag}{'packages'};
+ my $count = $stats{$tag}{'count'};
+ my $overrides = $stats{$tag}{'overrides'};
+ my $q_tag = html_quote($tag);
+ $OUT .= qq( <li><a href="${path_prefix}tags/${q_tag}.html">${q_tag}</a>)
+ . " ($packages packages, $count tags"
+ . ($overrides > 0 ? ", plus $overrides overrides" : "")
+ . ")</li>\n";
+ }
+ if ($heading) {
+ $OUT .= " </ul>\n\n";
+ }
+ }
+}
+{ foot() }
diff --git a/reporting/templates/tags.tmpl b/reporting/templates/tags.tmpl
new file mode 100644
index 0000000..3654af7
--- /dev/null
+++ b/reporting/templates/tags.tmpl
@@ -0,0 +1,34 @@
+{ head("Lintian Tags") }
+ <h1>Tags</h1>
+
+ <p>
+ This is a list of all tags that occur at least once in the archive
+ with their frequency counts. This includes all tags, even
+ experimental and info tags.
+ </p>
+
+ <ul>
+{
+ for my $tag (sort keys %stats) {
+ my $q_tag = html_quote($tag);
+ my $packages = $stats{$tag}{'packages'};
+ my $count = $stats{$tag}{'count'};
+ my $packages_str = $packages != 1 ?
+ "$packages packages" :
+ "$packages package";
+ my $count_str = $count != 1 ? "$count tags" : "$count tag";
+ my $overrides = $stats{$tag}{'overrides'};
+ my $overrides_str = '';
+ if ($overrides) {
+ if ($overrides == 1) {
+ $overrides_str = ", plus $overrides override";
+ } else {
+ $overrides_str = ", plus $overrides overrides";
+ }
+ }
+ $OUT .= qq( <li><a href="${path_prefix}tags/${q_tag}.html">${q_tag}</a>)
+ . " ($packages_str, ${count_str}${overrides_str}"
+ . ")</li>\n";
+ }
+} </ul>
+{ foot() }