Commit b27c6e99 authored by Nicolas Dandrimont's avatar Nicolas Dandrimont 🤔
Browse files

Overhaul the lintian plugin

parent 718f7d44
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# This file is part of debexpo - http://debexpo.workaround.org # This file is part of debexpo - http://debexpo.workaround.org
# #
# Copyright © 2008 Jonny Lamb <jonny@debian.org> # Copyright © 2008 Jonny Lamb <jonny@debian.org>
# Copyright © 2012 Nicolas Dandrimont <Nicolas.Dandrimont@crans.org>
# #
# Permission is hereby granted, free of charge, to any person # Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation # obtaining a copy of this software and associated documentation
...@@ -32,9 +33,13 @@ Holds the lintian plugin. ...@@ -32,9 +33,13 @@ Holds the lintian plugin.
""" """
__author__ = 'Jonny Lamb' __author__ = 'Jonny Lamb'
__copyright__ = 'Copyright © 2008 Jonny Lamb' __copyright__ = ', '.join([
'Copyright © 2008 Jonny Lamb',
'Copyright © 2012 Nicolas Dandrimont',
])
__license__ = 'MIT' __license__ = 'MIT'
from collections import defaultdict
import subprocess import subprocess
import logging import logging
...@@ -51,32 +56,61 @@ class LintianPlugin(BasePlugin): ...@@ -51,32 +56,61 @@ class LintianPlugin(BasePlugin):
""" """
log.debug('Running lintian on the package') log.debug('Running lintian on the package')
output = subprocess.Popen(["lintian", self.changes_file], stdout=subprocess.PIPE).communicate()[0] output = subprocess.Popen(["lintian",
"-E",
"-I",
"--pedantic",
"--show-overrides",
self.changes_file], stdout=subprocess.PIPE).communicate()[0]
items = output.split('\n') items = output.split('\n')
if items and output != '':
# Yes, three levels of defaultdict and one of list...
def defaultdict_defaultdict_list():
def defaultdict_list():
return defaultdict(list)
return defaultdict(defaultdict_list)
lintian_warnings = defaultdict(defaultdict_defaultdict_list)
lintian_severities = set()
override_comments = []
for item in items:
if not item:
continue
# lintian output is of the form """SEVERITY: package: lintian_tag [lintian tag arguments]""" or """N: Override comment"""
if item.startswith("N: "):
override_comments.append(item[3:].strip())
continue
severity, package, rest = item.split(': ', 2)
lintian_severities.add(severity)
lintian_tag_data = rest.split()
lintian_tag = lintian_tag_data[0]
lintian_data = lintian_tag_data[1:]
if override_comments:
lintian_data.append("(override comment: " + " ".join(override_comments) + ")")
override_comments = []
lintian_warnings[package][severity][lintian_tag].append(lintian_data)
severity = constants.PLUGIN_SEVERITY_INFO
if 'E' in lintian_severities:
severity = constants.PLUGIN_SEVERITY_ERROR
outcome = 'Package has lintian errors'
elif 'W' in lintian_severities:
severity = constants.PLUGIN_SEVERITY_WARNING severity = constants.PLUGIN_SEVERITY_WARNING
outcome = 'lintian-warnings' outcome = 'Package has lintian warnings'
logmessage = log.warning elif 'I' in lintian_severities:
for item in items: outcome = 'Package has lintian informational warnings'
if item.startswith('E:'): elif 'O' in lintian_severities:
severity = constants.PLUGIN_SEVERITY_ERROR outcome = 'Package has overridden lintian tags'
outcome = 'lintian-errors' elif 'P' in lintian_severities or 'X' in lintian_severities:
logmessage = log.error outcome = 'Package has lintian pedantic/experimental warnings'
break
logmessage('Package is not Lintian clean')
self.failed(outcome, output, severity)
self.info(outcome, None)
else: else:
log.debug('Package is Lintian clean') outcome = 'Package is lintian clean'
self.passed('lintian-clean', None, constants.PLUGIN_SEVERITY_INFO)
plugin = LintianPlugin self.failed(outcome, lintian_warnings, severity)
outcomes = { plugin = LintianPlugin
'lintian-clean' : { 'name' : 'Package is Lintian clean' },
'lintian-warnings' : { 'name' : 'Package has Lintian warnings' },
'lintian-errors' : { 'name' : 'Package has Lintian errors' },
}
...@@ -968,4 +968,62 @@ ul.qa { ...@@ -968,4 +968,62 @@ ul.qa {
background-color: #C7EA3C; background-color: #C7EA3C;
} }
/* Lintian plugin */
.qa .lintian-E {
background-color: #FF6700;
margin: 0 3px 0 0;
padding: 2px 4px;
font-family: monospace;
border: none;
}
.qa .lintian-W {
background-color: #FFEB44;
margin: 0 3px 0 0;
padding: 2px 4px;
font-family: monospace;
border: none;
}
.qa .lintian-P {
background-color: #C7EA3C;
margin: 0 3px 0 0;
padding: 2px 4px;
font-family: monospace;
border: none;
}
.qa .lintian-I {
background-color: #C7EA3C;
margin: 0 3px 0 0;
padding: 2px 4px;
font-family: monospace;
border: none;
}
.qa .lintian-X {
background-color: #EE99EE;
margin: 0 3px 0 0;
padding: 2px 4px;
font-family: monospace;
border: none;
}
.qa .lintian-O {
background-color: #DDD;
margin: 0 3px 0 0;
padding: 2px 4px;
font-family: monospace;
border: none;
}
.qa .lintian-pkgname {
font-weight: bold;
}
.qa .lintian-contents {
margin: 0;
margin-bottom: 1em;
list-style-type: none;
}
<%!
def decode_severity(s):
"""Decode a lintian severity"""
verbose_severity = {
'E': 'Error',
'W': 'Warning',
'P': 'Pedantic',
'I': 'Info',
'O': 'Override',
'X': 'Experimental',
}.get(s, '???')
return '''<span class="lintian-%(s)s" title="%(verbose_severity)s">%(s)s</span>''' % locals()
def tag_to_a(tag):
"""Return a link to the lintian tag description"""
return '<a href="http://lintian.debian.org/tags/%s.html">%s</a>' % (tag, tag)
def severity_key(x):
"""Key to sort lintian severities"""
return "EWIPOX".index(x)
%>
<div class="qa-header">
${o.outcome}
</div>
<div class="qa-content">
% if o.rich_data:
% for package in o.rich_data:
<div class="lintian-pkgname">
${package}
</div>
<ul class="lintian-contents">
% for severity in sorted(o.rich_data[package], key = severity_key):
% for tag in sorted(o.rich_data[package][severity]):
<li>
${decode_severity(severity)} ${tag_to_a(tag)}
% if any(o.rich_data[package][severity][tag]):
<ul>
% for data in o.rich_data[package][severity][tag]:
<li>${" ".join(data) | h}</li>
% endfor
</ul>
% endif
</li>
% endfor
% endfor
</ul>
% endfor
% endif
</div>
% if o.rich_data:
% for package in o.rich_data:
% for severity in o.rich_data[package]:
% for tag in sorted(o.rich_data[package][severity]):
% if any(o.rich_data[package][severity][tag]):
% for data in o.rich_data[package][severity][tag]:
${severity}: ${package}: ${tag} ${" ".join(data) | h}
% endfor
% endif
% endfor
% endfor
% endfor
% endif
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment