Commit 2aa8a438 authored by Jelmer Vernooij's avatar Jelmer Vernooij

Add support for a certainty tag in fixer output.

parent d25b722f
...@@ -72,3 +72,7 @@ It can include optional metadata in its output:: ...@@ -72,3 +72,7 @@ It can include optional metadata in its output::
links to documentation about the fixed lintian tags. In the future, links to documentation about the fixed lintian tags. In the future,
it may also support building the package to verify the lintian tag it may also support building the package to verify the lintian tag
is actually resolved. is actually resolved.
* ``Certainty:`` followed by ``certain`` or ``possible``,
indicating how certain the fixer is that the fix was the right
one.
...@@ -2,6 +2,7 @@ lintian-brush (0.6) UNRELEASED; urgency=medium ...@@ -2,6 +2,7 @@ lintian-brush (0.6) UNRELEASED; urgency=medium
* useless-autoreconf-build-depends: Actually require changes, don't * useless-autoreconf-build-depends: Actually require changes, don't
just update debhelper build-depends. just update debhelper build-depends.
* Add support for a certainty tag in fixer output.
-- Jelmer Vernooij <jelmer@debian.org> Mon, 05 Nov 2018 19:31:02 +0000 -- Jelmer Vernooij <jelmer@debian.org> Mon, 05 Nov 2018 19:31:02 +0000
......
...@@ -19,6 +19,7 @@ def bump_debhelper(control): ...@@ -19,6 +19,7 @@ def bump_debhelper(control):
control["Build-Depends"], control["Build-Depends"],
"dh-autoreconf") "dh-autoreconf")
changed = False changed = False
outf = StringIO() outf = StringIO()
with open('debian/rules', 'r') as f: with open('debian/rules', 'r') as f:
......
...@@ -44,6 +44,7 @@ from debian.deb822 import Deb822 ...@@ -44,6 +44,7 @@ from debian.deb822 import Deb822
__version__ = (0, 1) __version__ = (0, 1)
version_string = '.'.join(map(str, __version__)) version_string = '.'.join(map(str, __version__))
SUPPORTED_CERTAINTIES = ['certain', 'possible']
class NoChanges(Exception): class NoChanges(Exception):
...@@ -54,6 +55,10 @@ class FixerFailed(Exception): ...@@ -54,6 +55,10 @@ class FixerFailed(Exception):
"""Base class for fixer script failures.""" """Base class for fixer script failures."""
class UnsupportedCertainty(Exception):
"""Unsupported certainty."""
class FixerScriptFailed(FixerFailed): class FixerScriptFailed(FixerFailed):
"""Script failed to run.""" """Script failed to run."""
...@@ -89,9 +94,22 @@ class PendingChanges(Exception): ...@@ -89,9 +94,22 @@ class PendingChanges(Exception):
class FixerResult(object): class FixerResult(object):
"""Result of a fixer run.""" """Result of a fixer run."""
def __init__(self, description, fixed_lintian_tags=[]): def __init__(self, description, fixed_lintian_tags=[],
certainty=None):
self.description = description self.description = description
self.fixed_lintian_tags = fixed_lintian_tags self.fixed_lintian_tags = fixed_lintian_tags
self.certainty = certainty
def __repr__(self):
return "%s(%r, fixed_lintian_tags=%r, certainty=%r)" % (
self.description, self.fixed_lintian_tags, self.certainty)
def __eq__(self, other):
if type(other) != type(self):
return False
return ((self.description == other.description) and
(self.fixed_lintian_tags == other.fixed_lintian_tags) and
(self.certainty == other.certainty))
class Fixer(object): class Fixer(object):
...@@ -146,13 +164,19 @@ class ScriptFixer(Fixer): ...@@ -146,13 +164,19 @@ class ScriptFixer(Fixer):
description = description.decode('utf-8') description = description.decode('utf-8')
lines = [] lines = []
fixed_tags = [] fixed_tags = []
certainty = None
for line in description.splitlines(): for line in description.splitlines():
# TODO(jelmer): Do this in a slighly less hackish manner # TODO(jelmer): Do this in a slighly less hackish manner
if line.startswith('Fixed-Lintian-Tags: '): (key, value) = line.split(':', 1)
fixed_tags = line.split(':', 1)[1].strip().split(',') if key == 'Fixed-Lintian-Tags':
fixed_tags = value.strip().split(',')
elif key == 'Certainty':
certainty = value.strip()
else: else:
lines.append(line) lines.append(line)
return FixerResult('\n'.join(lines), fixed_tags) if certainty not in SUPPORTED_CERTAINTIES:
raise UnsupportedCertainty(certainty)
return FixerResult('\n'.join(lines), fixed_tags, certainty)
def find_fixers_dir(): def find_fixers_dir():
...@@ -271,7 +295,7 @@ def run_lintian_fixer(local_tree, fixer, committer=None, ...@@ -271,7 +295,7 @@ def run_lintian_fixer(local_tree, fixer, committer=None,
committer: Optional committer (name and email) committer: Optional committer (name and email)
update_changelog: Whether to add a new entry to the changelog update_changelog: Whether to add a new entry to the changelog
Returns: Returns:
summary of the changes tuple with set of FixerResult, summary of the changes
""" """
# Just check there are no changes to begin with # Just check there are no changes to begin with
if list(local_tree.iter_changes(local_tree.basis_tree())): if list(local_tree.iter_changes(local_tree.basis_tree())):
...@@ -324,7 +348,7 @@ def run_lintian_fixer(local_tree, fixer, committer=None, ...@@ -324,7 +348,7 @@ def run_lintian_fixer(local_tree, fixer, committer=None,
reporter=NullCommitReporter(), reporter=NullCommitReporter(),
committer=committer) committer=committer)
# TODO(jelmer): Run sbuild & verify lintian warning is gone? # TODO(jelmer): Run sbuild & verify lintian warning is gone?
return result.fixed_lintian_tags, summary return result, summary
def run_lintian_fixers(local_tree, fixers, update_changelog=True, def run_lintian_fixers(local_tree, fixers, update_changelog=True,
...@@ -339,19 +363,18 @@ def run_lintian_fixers(local_tree, fixers, update_changelog=True, ...@@ -339,19 +363,18 @@ def run_lintian_fixers(local_tree, fixers, update_changelog=True,
committer: Optional committer (name and email) committer: Optional committer (name and email)
Returns: Returns:
Tuple with two lists: Tuple with two lists:
list of tuples with (lintian-tag, description) of fixers that ran list of tuples with (lintian-tag, certainty, description) of fixers
list of script names for fixers that failed to run that ran list of script names for fixers that failed to run
""" """
failed_fixers = [] failed_fixers = []
fixers = list(fixers) fixers = list(fixers)
ret = [] ret = []
pb = ui.ui_factory.nested_progress_bar() with ui.ui_factory.nested_progress_bar() as pb:
try:
for i, fixer in enumerate(fixers): for i, fixer in enumerate(fixers):
pb.update('Running fixer %r on %s' % (fixer, local_tree.basedir), pb.update('Running fixer %r on %s' % (fixer, local_tree.basedir),
i, len(fixers)) i, len(fixers))
try: try:
fixed_lintian_tags, summary = run_lintian_fixer( result, summary = run_lintian_fixer(
local_tree, fixer, update_changelog=update_changelog, local_tree, fixer, update_changelog=update_changelog,
committer=committer) committer=committer)
except FixerFailed as e: except FixerFailed as e:
...@@ -365,7 +388,5 @@ def run_lintian_fixers(local_tree, fixers, update_changelog=True, ...@@ -365,7 +388,5 @@ def run_lintian_fixers(local_tree, fixers, update_changelog=True,
else: else:
if verbose: if verbose:
note('Fixer %r made changes.', fixer) note('Fixer %r made changes.', fixer)
ret.append((fixed_lintian_tags, summary)) ret.append((result, summary))
finally:
pb.finished()
return ret, failed_fixers return ret, failed_fixers
...@@ -105,8 +105,8 @@ def main(argv=None): ...@@ -105,8 +105,8 @@ def main(argv=None):
return 1 return 1
if applied: if applied:
all_tags = set() all_tags = set()
for tags, summary in applied: for result, summary in applied:
all_tags.update(tags) all_tags.update(result.fixed_lintian_tags)
note("Lintian tags fixed: %r" % all_tags) note("Lintian tags fixed: %r" % all_tags)
else: else:
note("No changes made.") note("No changes made.")
......
...@@ -79,7 +79,7 @@ class DummyFixer(Fixer): ...@@ -79,7 +79,7 @@ class DummyFixer(Fixer):
with open(os.path.join(basedir, 'debian/control'), 'a') as f: with open(os.path.join(basedir, 'debian/control'), 'a') as f:
f.write('a new line\n') f.write('a new line\n')
return FixerResult("Fixed some tag.\nExtended description.", return FixerResult("Fixed some tag.\nExtended description.",
['some-tag']) ['some-tag'], "certain")
class FailingFixer(Fixer): class FailingFixer(Fixer):
...@@ -140,11 +140,12 @@ Arch: all ...@@ -140,11 +140,12 @@ Arch: all
def test_simple_modify(self): def test_simple_modify(self):
with self.tree.lock_write(): with self.tree.lock_write():
fixed_tags, summary = run_lintian_fixer( result, summary = run_lintian_fixer(
self.tree, DummyFixer('dummy', 'some-tag'), self.tree, DummyFixer('dummy', 'some-tag'),
update_changelog=False) update_changelog=False)
self.assertEqual(summary, "Fixed some tag.") self.assertEqual(summary, "Fixed some tag.")
self.assertEqual(['some-tag'], fixed_tags) self.assertEqual(['some-tag'], result.fixed_lintian_tags)
self.assertEqual('certain', result.certainty)
self.assertEqual(2, self.tree.branch.revno()) self.assertEqual(2, self.tree.branch.revno())
self.assertEqual( self.assertEqual(
self.tree.get_file_lines('debian/control')[-1], self.tree.get_file_lines('debian/control')[-1],
...@@ -157,11 +158,12 @@ Arch: all ...@@ -157,11 +158,12 @@ Arch: all
f.write("test") f.write("test")
return FixerResult("Created new file.", ['some-tag']) return FixerResult("Created new file.", ['some-tag'])
with self.tree.lock_write(): with self.tree.lock_write():
fixed_tags, summary = run_lintian_fixer( result, summary = run_lintian_fixer(
self.tree, NewFileFixer('new-file', 'some-tag'), self.tree, NewFileFixer('new-file', 'some-tag'),
update_changelog=False) update_changelog=False)
self.assertEqual(summary, "Created new file.") self.assertEqual(summary, "Created new file.")
self.assertEqual(['some-tag'], fixed_tags) self.assertIs(None, result.certainty)
self.assertEqual(['some-tag'], result.fixed_lintian_tags)
rev = self.tree.branch.repository.get_revision( rev = self.tree.branch.repository.get_revision(
self.tree.last_revision()) self.tree.last_revision())
self.assertEqual(rev.message, ( self.assertEqual(rev.message, (
...@@ -185,11 +187,12 @@ Arch: all ...@@ -185,11 +187,12 @@ Arch: all
return FixerResult("Renamed a file.") return FixerResult("Renamed a file.")
orig_basis_tree = self.tree.branch.basis_tree() orig_basis_tree = self.tree.branch.basis_tree()
with self.tree.lock_write(): with self.tree.lock_write():
fixed_tags, summary = run_lintian_fixer( result, summary = run_lintian_fixer(
self.tree, RenameFileFixer('rename', 'some-tag'), self.tree, RenameFileFixer('rename', 'some-tag'),
update_changelog=False) update_changelog=False)
self.assertEqual(summary, "Renamed a file.") self.assertEqual(summary, "Renamed a file.")
self.assertEqual([], fixed_tags) self.assertIs(None, result.certainty)
self.assertEqual([], result.fixed_lintian_tags)
self.assertEqual(2, self.tree.branch.revno()) self.assertEqual(2, self.tree.branch.revno())
basis_tree = self.tree.branch.basis_tree() basis_tree = self.tree.branch.basis_tree()
with basis_tree.lock_read(), orig_basis_tree.lock_read(): with basis_tree.lock_read(), orig_basis_tree.lock_read():
...@@ -272,7 +275,11 @@ Arch: all ...@@ -272,7 +275,11 @@ Arch: all
applied, failed = run_lintian_fixers( applied, failed = run_lintian_fixers(
self.tree, [DummyFixer('dummy', 'some-tag')], self.tree, [DummyFixer('dummy', 'some-tag')],
update_changelog=False) update_changelog=False)
self.assertEqual([(['some-tag'], 'Fixed some tag.')], applied) self.assertEqual(
[(FixerResult("Fixed some tag.\nExtended description.",
['some-tag'], 'certain'),
'Fixed some tag.')],
applied)
self.assertEqual([], failed) self.assertEqual([], failed)
self.assertEqual(2, self.tree.branch.revno()) self.assertEqual(2, self.tree.branch.revno())
self.assertEqual( self.assertEqual(
...@@ -302,11 +309,12 @@ Arch: all ...@@ -302,11 +309,12 @@ Arch: all
def make_change(self, tree, committer=None): def make_change(self, tree, committer=None):
with tree.lock_write(): with tree.lock_write():
fixed_tags, summary = run_lintian_fixer( result, summary = run_lintian_fixer(
tree, DummyFixer('dummy', 'some-tag'), tree, DummyFixer('dummy', 'some-tag'),
update_changelog=False, committer=committer) update_changelog=False, committer=committer)
self.assertEqual(summary, "Fixed some tag.") self.assertEqual(summary, "Fixed some tag.")
self.assertEqual(['some-tag'], fixed_tags) self.assertEqual(['some-tag'], result.fixed_lintian_tags)
self.assertEqual('certain', result.certainty)
self.assertEqual(2, tree.branch.revno()) self.assertEqual(2, tree.branch.revno())
self.assertEqual( self.assertEqual(
tree.get_file_lines('debian/control')[-1], tree.get_file_lines('debian/control')[-1],
......
Markdown is supported
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