diff --git a/britney.py b/britney.py index a676863..bc1fb99 100755 --- a/britney.py +++ b/britney.py @@ -213,6 +213,7 @@ from britney2.utils import (log_and_format_old_libraries, get_dependency_solvers invalidate_excuses, compile_nuninst, find_smooth_updateable_binaries, parse_provides, MigrationConstraintException, + check_target_suite_source_pkg_consistency, ) __author__ = 'Fabio Tranchitella and the Debian Release Team' @@ -477,6 +478,11 @@ class Britney(object): self.options.ignore_cruft == "0": self.options.ignore_cruft = False + if not hasattr(self.options, 'check_consistency_level'): + self.options.check_consistency_level = 2 + else: + self.options.check_consistency_level = int(self.options.check_consistency_level) + if not hasattr(self.options, 'adt_retry_url_mech'): self.options.adt_retry_url_mech = '' @@ -1480,6 +1486,8 @@ class Britney(object): output_logger.info(" most: (%d) .. %s", len(selected), " ".join(x.uvname for x in selected[-20:])) + if self.options.check_consistency_level >= 3: + check_target_suite_source_pkg_consistency(self.suite_info, "iter_packages after commit", self.logger) nuninst_last_accepted = nuninst_after rescheduled_packages.extend(maybe_rescheduled_packages) maybe_rescheduled_packages.clear() @@ -1499,6 +1507,8 @@ class Britney(object): ) output_logger.info(" got: %s", self.eval_nuninst(nuninst_after, compare_nuninst)) output_logger.info(" * %s: %s", failed_arch, ", ".join(broken)) + if self.options.check_consistency_level >= 3: + check_target_suite_source_pkg_consistency(self.suite_info, "iter_package after rollback (not accepted)",self.logger) except MigrationConstraintException as e: transaction.rollback() @@ -1509,6 +1519,8 @@ class Britney(object): len(worklist) ) output_logger.info(" got exception: %s"%(repr(e))) + if self.options.check_consistency_level >= 3: + check_target_suite_source_pkg_consistency(self.suite_info, "iter_package after rollback (MigrationConstraintException)",self.logger) if not accepted: if len(comp) > 1: @@ -1659,6 +1671,8 @@ class Britney(object): self.all_selected += selected if transaction: transaction.commit() + if self.options.check_consistency_level >= 2: + check_target_suite_source_pkg_consistency(self.suite_info, "do_all after commit", self.logger) if not actions: if recurse: self.upgrade_me = extra @@ -1669,6 +1683,8 @@ class Britney(object): if not transaction: return transaction.rollback() + if self.options.check_consistency_level >= 2: + check_target_suite_source_pkg_consistency(self.suite_info, "do_all after rollback", self.logger) output_logger.info("") @@ -1804,7 +1820,9 @@ class Britney(object): log_and_format_old_libraries(self.output_logger, removals) self.printuninstchange() - self.assert_nuninst_is_correct() + if self.options.check_consistency_level >= 1: + self.assert_nuninst_is_correct() + check_target_suite_source_pkg_consistency(self.suite_info, "end", self.logger) # output files if not self.options.dry_run: diff --git a/britney2/utils.py b/britney2/utils.py index fe154bd..21f9cbf 100644 --- a/britney2/utils.py +++ b/britney2/utils.py @@ -336,6 +336,32 @@ def old_libraries(mi_factory, suite_info, outofsync_arches=frozenset()): removals.append(mi_factory.generate_removal_for_cruft_item(pkg.pkg_id)) return removals +def check_target_suite_source_pkg_consistency(suite_info, comment, logger): + sources_t = suite_info.target_suite.sources + binaries_t = suite_info.target_suite.binaries + issues_found = False + + logger.info("check_target_suite_source_pkg_consistency %s",comment) + + for arch in binaries_t: + for pkg_name in binaries_t[arch]: + pkg = binaries_t[arch][pkg_name] + src = pkg.source + + if src not in sources_t: + issues_found = True + logger.error("inconsistency found (%s): src %s not in target, target has pkg %s with source %s"%(comment,src,pkg_name,src)) + + for src in sources_t: + source_data = sources_t[src] + for pkg_id in source_data.binaries: + binary, _, parch = pkg_id + if binary not in binaries_t[parch]: + issues_found = True + logger.error("inconsistency found (%s): binary %s from source %s not in binaries_t[%s]"%(comment,binary,src,parch)) + + if issues_found: + raise AssertionError("inconsistencies found in target suite") def is_nuninst_asgood_generous(constraints, architectures, old, new, break_arches=frozenset()): """Compares the nuninst counters and constraints to see if they improved