def test_rename_file(self): tree = self.make_test_tree() class RenameFileFixer(Fixer): def run(self, basedir, package, *args, **kwargs): os.rename( os.path.join(basedir, "debian/control"), os.path.join(basedir, "debian/control.blah"), ) return FixerResult("Renamed a file.") orig_basis_tree = tree.branch.basis_tree() with tree.lock_write(): result, summary = run_lintian_fixer(tree, RenameFileFixer( "rename", "some-tag"), update_changelog=False) self.assertEqual(summary, "Renamed a file.") self.assertIs(None, result.certainty) self.assertEqual([], result.fixed_lintian_tags) self.assertEqual(2, tree.branch.revno()) basis_tree = tree.branch.basis_tree() with basis_tree.lock_read(), orig_basis_tree.lock_read(): self.assertFalse(basis_tree.has_filename("debian/control")) self.assertTrue(basis_tree.has_filename("debian/control.blah")) self.assertNotEqual(orig_basis_tree.get_revision_id(), basis_tree.get_revision_id()) self.expectFailure( "mv --auto appears to be broken", self.assertEqual, basis_tree.path2id("debian/control.blah"), orig_basis_tree.path2id("debian/control"), )
def test_new_file(self): tree = self.make_test_tree() class NewFileFixer(Fixer): def run(self, basedir, package, *args, **kwargs): with open(os.path.join(basedir, "debian/somefile"), "w") as f: f.write("test") return FixerResult("Created new file.", ["some-tag"]) with tree.lock_write(): result, summary = run_lintian_fixer(tree, NewFileFixer( "new-file", "some-tag"), update_changelog=False) self.assertEqual(summary, "Created new file.") self.assertIs(None, result.certainty) self.assertEqual(["some-tag"], result.fixed_lintian_tags) rev = tree.branch.repository.get_revision(tree.last_revision()) self.assertEqual( rev.message, ("Created new file.\n" "\n" "Changes-By: lintian-brush\n" "Fixes: lintian: some-tag\n" "See-also: https://lintian.debian.org/tags/some-tag.html\n"), ) self.assertEqual(2, tree.branch.revno()) basis_tree = tree.branch.basis_tree() with basis_tree.lock_read(): self.assertEqual(basis_tree.get_file_text("debian/somefile"), b"test")
def test_simple_modify(self): tree = self.make_test_tree() with tree.lock_write(): result, summary = run_lintian_fixer(tree, DummyFixer( "dummy", "some-tag"), update_changelog=False) self.assertEqual(summary, "Fixed some tag.") self.assertEqual(["some-tag"], result.fixed_lintian_tags) self.assertEqual("certain", result.certainty) self.assertEqual(2, tree.branch.revno()) self.assertEqual( tree.get_file_lines("debian/control")[-1], b"a new line\n")
def make_change(self, tree, committer=None): with tree.lock_write(): result, summary = run_lintian_fixer( tree, DummyFixer("dummy", "some-tag"), update_changelog=False, committer=committer, ) self.assertEqual(summary, "Fixed some tag.") self.assertEqual(["some-tag"], result.fixed_lintian_tags) self.assertEqual("certain", result.certainty) self.assertEqual(2, tree.branch.revno()) self.assertEqual( tree.get_file_lines("debian/control")[-1], b"a new line\n")
def test_simple_modify_acceptably_uncertain(self): tree = self.make_test_tree() class UncertainFixer(Fixer): def run(self, basedir, package, *args, **kwargs): with open(os.path.join(basedir, "debian/somefile"), "w") as f: f.write("test") return FixerResult("Renamed a file.", certainty="possible") with tree.lock_write(): result, summary = run_lintian_fixer( tree, UncertainFixer("dummy", "some-tag"), update_changelog=False, minimum_certainty="possible", ) self.assertEqual(2, tree.branch.revno())
def test_upstream_change(self): tree = self.make_test_tree(version="0.1-1") class NewFileFixer(Fixer): def run(self, basedir, package, *args, **kwargs): with open(os.path.join(basedir, "configure.ac"), "w") as f: f.write("AC_INIT(foo, bar)\n") return FixerResult("Created new configure.ac.", [], patch_name="add-config") with tree.lock_write(): result, summary = run_lintian_fixer( tree, NewFileFixer("add-config", "add-config"), update_changelog=False, timestamp=datetime(2020, 9, 8, 0, 36, 35, 857836), ) self.assertEqual( summary, "Add patch add-config.patch: Created new configure.ac.") self.assertIs(None, result.certainty) self.assertEqual([], result.fixed_lintian_tags) rev = tree.branch.repository.get_revision(tree.last_revision()) self.assertEqual( rev.message, ("Created new configure.ac.\n" "\n" "Changes-By: lintian-brush\n"), ) self.assertEqual(2, tree.branch.revno()) basis_tree = tree.branch.basis_tree() with basis_tree.lock_read(): self.assertEqual(basis_tree.get_file_text("debian/patches/series"), b"add-config.patch\n") lines = basis_tree.get_file_lines( "debian/patches/add-config.patch") self.assertEqual(lines[0], b"Description: Created new configure.ac.\n") self.assertEqual(lines[1], b"Origin: other\n") self.assertEqual(lines[2], b"Last-Update: 2020-09-08\n") self.assertEqual(lines[3], b"\n") self.assertEqual(lines[4], b"=== added file 'configure.ac'\n") self.assertEqual(lines[7], b"@@ -0,0 +1,1 @@\n") self.assertEqual(lines[8], b"+AC_INIT(foo, bar)\n")
def make_changes( self, local_tree, subpath, update_changelog, reporter, committer, base_proposal=None, ): from lintian_brush import NoChanges from lintian_brush.multiarch_hints import ( MultiArchHintFixer, ) base_revid = local_tree.last_revision() minimum_certainty = self.minimum_certainty allow_reformatting = self.allow_reformatting try: cfg = Config.from_workingtree(local_tree, subpath) except FileNotFoundError: pass else: if minimum_certainty is None: minimum_certainty = cfg.minimum_certainty() if allow_reformatting is None: allow_reformatting = cfg.allow_reformatting() if update_changelog is None: update_changelog = cfg.update_changelog() if control_files_in_root(local_tree, subpath): raise ChangerError( "control-files-in-root", "control files live in root rather than debian/ " "(LarstIQ mode)", ) if is_debcargo_package(local_tree, subpath): raise ChangerError("nothing-to-do", "Package uses debcargo") elif not control_file_present(local_tree, subpath): raise ChangerError("missing-control-file", "Unable to find debian/control") try: with local_tree.lock_write(): result, summary = run_lintian_fixer( local_tree, MultiArchHintFixer(self.hints), update_changelog=update_changelog, minimum_certainty=minimum_certainty, subpath=subpath, allow_reformatting=allow_reformatting, net_access=True, committer=committer, changes_by="apply-multiarch-hints", ) except NoChanges: raise ChangerError("nothing-to-do", "no hints to apply") except FormattingUnpreservable as e: raise ChangerError( "formatting-unpreservable", "unable to preserve formatting while editing %s" % e.path, ) except GeneratedFile as e: raise ChangerError("generated-file", "unable to edit generated file: %r" % e) applied_hints = [] hint_names = [] for (binary, hint, description, certainty) in result.changes: hint_names.append(hint["link"].split("#")[-1]) entry = dict(hint.items()) hint_names.append(entry["link"].split("#")[-1]) entry["action"] = description entry["certainty"] = certainty applied_hints.append(entry) logging.info("%s: %s" % (binary["Package"], description)) reporter.report_metadata("applied-hints", applied_hints) branches = [("main", None, base_revid, local_tree.last_revision())] tags = [] return ChangerResult( description="Applied multi-arch hints.", mutator=result, branches=branches, tags=tags, value=calculate_value(hint_names), sufficient_for_proposal=True, proposed_commit_message="Apply multi-arch hints.", )
def main(argv=None): # noqa: C901 import argparse from breezy.workingtree import WorkingTree import breezy # noqa: E402 breezy.initialize() import breezy.git # noqa: E402 import breezy.bzr # noqa: E402 from .config import Config parser = argparse.ArgumentParser(prog="multi-arch-fixer") parser.add_argument( "--directory", metavar="DIRECTORY", help="directory to run in", type=str, default=".", ) parser.add_argument( "--disable-inotify", action="store_true", default=False, help=argparse.SUPPRESS ) parser.add_argument( "--identity", help="Print user identity that would be used when committing", action="store_true", default=False, ) # Hide the minimum-certainty option for the moment. parser.add_argument( "--minimum-certainty", type=str, choices=SUPPORTED_CERTAINTIES, default=None, help=argparse.SUPPRESS, ) parser.add_argument( "--no-update-changelog", action="store_false", default=None, dest="update_changelog", help="do not update the changelog", ) parser.add_argument( "--update-changelog", action="store_true", dest="update_changelog", help="force updating of the changelog", default=None, ) parser.add_argument( "--version", action="version", version="%(prog)s " + version_string ) parser.add_argument( "--allow-reformatting", default=None, action="store_true", help=argparse.SUPPRESS, ) args = parser.parse_args(argv) logging.basicConfig(level=logging.INFO, format='%(message)s') minimum_certainty = args.minimum_certainty wt, subpath = WorkingTree.open_containing(args.directory) if args.identity: logging.info('%s', get_committer(wt)) return 0 update_changelog = args.update_changelog allow_reformatting = args.allow_reformatting try: cfg = Config.from_workingtree(wt, subpath) except FileNotFoundError: pass else: if minimum_certainty is None: minimum_certainty = cfg.minimum_certainty() if allow_reformatting is None: allow_reformatting = cfg.allow_reformatting() if update_changelog is None: update_changelog = cfg.update_changelog() use_inotify = ((False if args.disable_inotify else None),) try: check_clean_tree(wt, wt.basis_tree(), subpath) except WorkspaceDirty: logging.info("%s: Please commit pending changes first.", wt.basedir) return 1 dirty_tracker = get_dirty_tracker(wt, subpath, use_inotify) if dirty_tracker: dirty_tracker.mark_clean() with cache_download_multiarch_hints() as f: hints = multiarch_hints_by_binary(parse_multiarch_hints(f)) if control_files_in_root(wt, subpath): report_fatal( "control-files-in-root", "control files live in root rather than debian/ " "(LarstIQ mode)", ) return 1 if is_debcargo_package(wt, subpath): report_okay("nothing-to-do", "Package uses debcargo") return 0 if not control_file_present(wt, subpath): report_fatal("missing-control-file", "Unable to find debian/control") return 1 try: result, summary = run_lintian_fixer( wt, MultiArchHintFixer(hints), update_changelog=update_changelog, minimum_certainty=minimum_certainty, dirty_tracker=dirty_tracker, subpath=subpath, allow_reformatting=allow_reformatting, net_access=True, changes_by="apply-multiarch-hints", ) except NoChanges: report_okay("nothing-to-do", "no hints to apply") return 0 except FormattingUnpreservable as e: report_fatal( "formatting-unpreservable", "unable to preserve formatting while editing %s" % e.path, ) return 1 except GeneratedFile as e: report_fatal( "generated-file", "unable to edit generated file: %r" % e) return 1 except NotDebianPackage: logging.info("%s: Not a debian package.", wt.basedir) return 1 else: applied_hints = [] hint_names = [] for (binary, hint, description, certainty) in result.changes: hint_names.append(hint["link"].split("#")[-1]) entry = dict(hint.items()) hint_names.append(entry["link"].split("#")[-1]) entry["action"] = description entry["certainty"] = certainty applied_hints.append(entry) logging.info("%s: %s" % (binary["Package"], description)) if os.environ.get('SVP_API') == '1': with open(os.environ['SVP_RESULT'], 'w') as f: json.dump({ 'description': "Applied multi-arch hints.", 'value': calculate_value(hint_names), 'commit-message': 'Apply multi-arch hints', 'context': { 'applied-hints': applied_hints, }}, f)