From f8a1c5eb60937eba46346c4096294cd2fa57cf3b Mon Sep 17 00:00:00 2001 From: Dimitri John Ledkov Date: Thu, 18 Feb 2016 14:02:31 +0000 Subject: [PATCH] Teach excuse_unsat_deps() about components ogre model --- britney.py | 21 +++++++++++++------ britney_util.py | 33 ++++++++++++++++++++++++++++- consts.py | 6 ++++++ tests/test_util.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 7 deletions(-) create mode 100755 tests/test_util.py diff --git a/britney.py b/britney.py index b22d3b7..a31d213 100755 --- a/britney.py +++ b/britney.py @@ -211,13 +211,13 @@ from britney_util import (old_libraries_format, undo_changes, old_libraries, is_nuninst_asgood_generous, clone_nuninst, check_installability, create_provides_map, - ensuredir, + ensuredir, get_component, allowed_component, ) from policies.policy import AgePolicy, RCBugPolicy, LPBlockBugPolicy, PolicyVerdict # Check the "check_field_name" reflection before removing an import here. from consts import (SOURCE, SOURCEVER, ARCHITECTURE, CONFLICTS, DEPENDS, - PROVIDES, MULTIARCH) + PROVIDES, MULTIARCH, MULTIVERSE) __author__ = 'Fabio Tranchitella and the Debian Release Team' __version__ = '2.0' @@ -1222,7 +1222,7 @@ class Britney(object): # Utility methods for package analysis # ------------------------------------ - def get_dependency_solvers(self, block, packages_s_a, empty_set=frozenset()): + def get_dependency_solvers(self, block, packages_s_a, empty_set=frozenset(), component=MULTIVERSE): """Find the packages which satisfy a dependency block This method returns the list of packages which satisfy a dependency @@ -1232,6 +1232,12 @@ class Britney(object): It returns a tuple with two items: the first is a boolean which is True if the dependency is satisfied, the second is the list of the solving packages. + + If component was not specified, use all availalbe + (multiverse). This is to avoid britney pretending that a bunch + of things are non-installable in release pocket, and start + trading components-missmatches things. + """ packages = [] binaries_s_a, provides_s_a = packages_s_a @@ -1250,7 +1256,9 @@ class Britney(object): # (if present) if (op == '' and version == '') or apt_pkg.check_dep(package.version, op, version): if archqual is None or (archqual == 'any' and package.multi_arch == 'allowed'): - packages.append(name) + # Don't check components when testing PPAs, as they do not have this concept + if self.options.adt_ppas or allowed_component(component, get_component(package.section)): + packages.append(name) # look for the package in the virtual packages list and loop on them for prov, prov_version in provides_s_a.get(name, empty_set): @@ -1295,11 +1303,12 @@ class Britney(object): return True is_all_ok = True + component = get_component(binary_u.section) # for every dependency block (formed as conjunction of disjunction) for block, block_txt in zip(parse_depends(deps), deps.split(',')): # if the block is satisfied in testing, then skip the block - packages = get_dependency_solvers(block, packages_t_a) + packages = get_dependency_solvers(block, packages_t_a, frozenset(), component) if packages: for p in packages: if p not in binaries_s_a: @@ -1308,7 +1317,7 @@ class Britney(object): continue # check if the block can be satisfied in the source suite, and list the solving packages - packages = get_dependency_solvers(block, packages_s_a) + packages = get_dependency_solvers(block, packages_s_a, frozenset(), component) packages = [packages_s_a[0][p].source for p in packages] # if the dependency can be satisfied by the same source package, skip the block: diff --git a/britney_util.py b/britney_util.py index 01f17d7..cd94cd4 100644 --- a/britney_util.py +++ b/britney_util.py @@ -35,7 +35,7 @@ from migrationitem import MigrationItem, UnversionnedMigrationItem from consts import (VERSION, PROVIDES, DEPENDS, CONFLICTS, ARCHITECTURE, SECTION, SOURCE, MAINTAINER, MULTIARCH, - ESSENTIAL) + ESSENTIAL, MAIN, RESTRICTED, UNIVERSE, MULTIVERSE) def ifilter_except(container, iterable=None): @@ -684,3 +684,34 @@ def create_provides_map(packages): provides[provided_pkg].add((pkg, provided_version)) return provides + + +def get_component(section): + """Parse section and return component + + Given a section, return component. Packages in MAIN have no + prefix, all others have / prefix. + """ + name2component = { + "restricted": RESTRICTED, + "universe": UNIVERSE, + "multiverse": MULTIVERSE + } + + if '/' in section: + return name2component[section.split('/', 1)[0]] + + return MAIN + + +def allowed_component(me, dep): + """Check if I can depend on the other component""" + + component_dependencies = { + MAIN: [MAIN], + RESTRICTED: [MAIN, RESTRICTED], + UNIVERSE: [MAIN, UNIVERSE], + MULTIVERSE: [MAIN, RESTRICTED, UNIVERSE, MULTIVERSE], + } + + return dep in component_dependencies[me] diff --git a/consts.py b/consts.py index 8f760d1..ceaa61b 100644 --- a/consts.py +++ b/consts.py @@ -34,3 +34,9 @@ DEPENDS = 6 CONFLICTS = 7 PROVIDES = 8 ESSENTIAL = 9 + +# components +MAIN = 0 +RESTRICTED = 1 +UNIVERSE = 2 +MULTIVERSE = 3 diff --git a/tests/test_util.py b/tests/test_util.py new file mode 100755 index 0000000..f2e79cb --- /dev/null +++ b/tests/test_util.py @@ -0,0 +1,52 @@ +#!/usr/bin/python3 +# (C) 2014 - 2016 Canonical Ltd. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +import os +import sys +import unittest + +PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, PROJECT_DIR) + +from britney_util import get_component, allowed_component +from consts import MAIN, RESTRICTED, UNIVERSE, MULTIVERSE + + +class UtilTests(unittest.TestCase): + + def test_get_component(self): + self.assertEqual(get_component('utils'), MAIN) + self.assertEqual(get_component('utils'), MAIN) + self.assertEqual(get_component('restricted/admin'), RESTRICTED) + self.assertEqual(get_component('universe/web'), UNIVERSE) + self.assertEqual(get_component('multiverse/libs'), MULTIVERSE) + + def test_allowed_component(self): + self.assertTrue(allowed_component(MAIN, MAIN)) + self.assertFalse(allowed_component(MAIN, UNIVERSE)) + self.assertFalse(allowed_component(MAIN, MULTIVERSE)) + self.assertFalse(allowed_component(MAIN, RESTRICTED)) + + self.assertTrue(allowed_component(RESTRICTED, MAIN)) + self.assertFalse(allowed_component(RESTRICTED, UNIVERSE)) + self.assertFalse(allowed_component(RESTRICTED, MULTIVERSE)) + self.assertTrue(allowed_component(RESTRICTED, RESTRICTED)) + + self.assertTrue(allowed_component(UNIVERSE, MAIN)) + self.assertTrue(allowed_component(UNIVERSE, UNIVERSE)) + self.assertFalse(allowed_component(UNIVERSE, MULTIVERSE)) + self.assertFalse(allowed_component(UNIVERSE, RESTRICTED)) + + self.assertTrue(allowed_component(MULTIVERSE, MAIN)) + self.assertTrue(allowed_component(MULTIVERSE, UNIVERSE)) + self.assertTrue(allowed_component(MULTIVERSE, MULTIVERSE)) + self.assertTrue(allowed_component(MULTIVERSE, RESTRICTED)) + + +if __name__ == '__main__': + unittest.main()