Merge lp:~xnox/britney/deps-components into lp:~ubuntu-release/britney/britney2-ubuntu

Proposed by Dimitri John Ledkov
Status: Merged
Merged at revision: 583
Proposed branch: lp:~xnox/britney/deps-components
Merge into: lp:~ubuntu-release/britney/britney2-ubuntu
Diff against target: 203 lines (+109/-8)
4 files modified
britney.py (+18/-7)
britney_util.py (+32/-1)
consts.py (+7/-0)
tests/test_util.py (+52/-0)
To merge this branch: bzr merge lp:~xnox/britney/deps-components
Reviewer Review Type Date Requested Status
Martin Pitt (community) Approve
Colin Watson Pending
Ubuntu Release Team Pending
Review via email: mp+286511@code.launchpad.net

Description of the change

Teach excuse_unsat_deps() about components ogre model.

This does not change other instalability tests, to hopefully, avoid britney trading all components mismatches around.

With this, components-mismatched things should stop migrating.

To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote :

I did not run britney with this change in, not sure how to.

All tests do pass, but they are limited in coverage.

Revision history for this message
Dimitri John Ledkov (xnox) wrote :

Run it, britney did not crash and found a buggy package already:

maas (1.9.0+bzr4533-0ubuntu1 to 1.10.0+bzr4578-0ubuntu2)
Maintainer: Ubuntu Developers
0 days old
python3-maas-provisioningserver/amd64 unsatisfiable Depends: python3-distro-info
Not considered

vs

maas (1.9.0+bzr4533-0ubuntu1 to 1.10.0+bzr4578-0ubuntu2)
Maintainer: Ubuntu Developers
7 days old
Valid candidate

Revision history for this message
Martin Pitt (pitti) wrote :

It's quite important to add some integration tests for this, but this doesn't need to block the initial rollout. LGTM otherwise, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'britney.py'
2--- britney.py 2016-02-16 09:18:43 +0000
3+++ britney.py 2016-02-18 14:08:15 +0000
4@@ -208,10 +208,11 @@
5 eval_uninst, newly_uninst, make_migrationitem,
6 write_excuses, write_heidi_delta, write_controlfiles,
7 old_libraries, is_nuninst_asgood_generous, ensuredir,
8- clone_nuninst)
9+ clone_nuninst, get_component, allowed_component)
10 from consts import (VERSION, SECTION, BINARIES, MAINTAINER, FAKESRC,
11- SOURCE, SOURCEVER, ARCHITECTURE, DEPENDS, CONFLICTS,
12- PROVIDES, RDEPENDS, RCONFLICTS, MULTIARCH, ESSENTIAL)
13+ SOURCE, SOURCEVER, ARCHITECTURE, DEPENDS, CONFLICTS,
14+ PROVIDES, RDEPENDS, RCONFLICTS, MULTIARCH, ESSENTIAL,
15+ COMPONENT, MULTIVERSE)
16 from autopkgtest import AutoPackageTest, srchash
17
18
19@@ -710,6 +711,7 @@
20 [],
21 [],
22 ess,
23+ get_component(get_field('Section'))
24 ]
25
26 # retrieve the name and the version of the source package
27@@ -1105,7 +1107,7 @@
28 # Utility methods for package analysis
29 # ------------------------------------
30
31- def get_dependency_solvers(self, block, arch, distribution):
32+ def get_dependency_solvers(self, block, arch, distribution, component=MULTIVERSE):
33 """Find the packages which satisfy a dependency block
34
35 This method returns the list of packages which satisfy a dependency
36@@ -1115,6 +1117,12 @@
37 It returns a tuple with two items: the first is a boolean which is
38 True if the dependency is satisfied, the second is the list of the
39 solving packages.
40+
41+ If component was not specified, use all availalbe
42+ (multiverse). This is to avoid britney pretending that a bunch
43+ of things are non-installable in release pocket, and start
44+ trading components-missmatches things.
45+
46 """
47
48 packages = []
49@@ -1136,7 +1144,8 @@
50 # (if present)
51 if (op == '' and version == '') or apt_pkg.check_dep(package[VERSION], op, version):
52 if archqual is None or (archqual == 'any' and package[MULTIARCH] == 'allowed'):
53- packages.append(name)
54+ if allowed_component(component, package[COMPONENT]):
55+ packages.append(name)
56
57 # look for the package in the virtual packages list and loop on them
58 for prov in binaries[1].get(name, []):
59@@ -1193,12 +1202,14 @@
60 return True
61 deps = binary_u[DEPENDS]
62
63+ component = binary_u[COMPONENT]
64+
65 all_satisfiable = True
66
67 # for every dependency block (formed as conjunction of disjunction)
68 for block, block_txt in zip(parse_depends(deps, False), deps.split(',')):
69 # if the block is satisfied in testing, then skip the block
70- packages = get_dependency_solvers(block, arch, 'testing')
71+ packages = get_dependency_solvers(block, arch, 'testing', component)
72 if packages:
73 for p in packages:
74 if p not in self.binaries[suite][arch][0]: continue
75@@ -1206,7 +1217,7 @@
76 continue
77
78 # check if the block can be satisfied in unstable, and list the solving packages
79- packages = get_dependency_solvers(block, arch, suite)
80+ packages = get_dependency_solvers(block, arch, suite, component)
81 packages = [self.binaries[suite][arch][0][p][SOURCE] for p in packages]
82
83 # if the dependency can be satisfied by the same source package, skip the block:
84
85=== modified file 'britney_util.py'
86--- britney_util.py 2015-08-24 18:46:42 +0000
87+++ britney_util.py 2016-02-18 14:08:15 +0000
88@@ -35,7 +35,7 @@
89 from consts import (VERSION, BINARIES, PROVIDES, DEPENDS, CONFLICTS,
90 RDEPENDS, RCONFLICTS, ARCHITECTURE, SECTION,
91 SOURCE, SOURCEVER, MAINTAINER, MULTIARCH,
92- ESSENTIAL)
93+ ESSENTIAL, MAIN, RESTRICTED, UNIVERSE, MULTIVERSE)
94
95 binnmu_re = re.compile(r'^(.*)\+b\d+$')
96
97@@ -620,3 +620,34 @@
98 clone[arch] = set(x for x in nuninst[arch] if x in packages_s[arch][0])
99 clone[arch + "+all"] = set(x for x in nuninst[arch + "+all"] if x in packages_s[arch][0])
100 return clone
101+
102+
103+def get_component(section):
104+ """Parse section and return component
105+
106+ Given a section, return component. Packages in MAIN have no
107+ prefix, all others have <component>/ prefix.
108+ """
109+ name2component = {
110+ "restricted": RESTRICTED,
111+ "universe": UNIVERSE,
112+ "multiverse": MULTIVERSE
113+ }
114+
115+ if '/' in section:
116+ return name2component[section.split('/', 1)[0]]
117+
118+ return MAIN
119+
120+
121+def allowed_component(me, dep):
122+ """Check if I can depend on the other component"""
123+
124+ component_dependencies = {
125+ MAIN: [MAIN],
126+ RESTRICTED: [MAIN, RESTRICTED],
127+ UNIVERSE: [MAIN, UNIVERSE],
128+ MULTIVERSE: [MAIN, RESTRICTED, UNIVERSE, MULTIVERSE],
129+ }
130+
131+ return dep in component_dependencies[me]
132
133=== modified file 'consts.py'
134--- consts.py 2015-07-01 13:49:06 +0000
135+++ consts.py 2016-02-18 14:08:15 +0000
136@@ -37,3 +37,10 @@
137 RDEPENDS = 9
138 RCONFLICTS = 10
139 ESSENTIAL = 11
140+COMPONENT = 12
141+
142+# components
143+MAIN = 0
144+RESTRICTED = 1
145+UNIVERSE = 2
146+MULTIVERSE = 3
147
148=== added file 'tests/test_util.py'
149--- tests/test_util.py 1970-01-01 00:00:00 +0000
150+++ tests/test_util.py 2016-02-18 14:08:15 +0000
151@@ -0,0 +1,52 @@
152+#!/usr/bin/python3
153+# (C) 2014 - 2016 Canonical Ltd.
154+#
155+# This program is free software; you can redistribute it and/or modify
156+# it under the terms of the GNU General Public License as published by
157+# the Free Software Foundation; either version 2 of the License, or
158+# (at your option) any later version.
159+
160+import os
161+import sys
162+import unittest
163+
164+PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
165+sys.path.insert(0, PROJECT_DIR)
166+
167+from britney_util import get_component, allowed_component
168+from consts import MAIN, RESTRICTED, UNIVERSE, MULTIVERSE
169+
170+
171+class UtilTests(unittest.TestCase):
172+
173+ def test_get_component(self):
174+ self.assertEqual(get_component('utils'), MAIN)
175+ self.assertEqual(get_component('utils'), MAIN)
176+ self.assertEqual(get_component('restricted/admin'), RESTRICTED)
177+ self.assertEqual(get_component('universe/web'), UNIVERSE)
178+ self.assertEqual(get_component('multiverse/libs'), MULTIVERSE)
179+
180+ def test_allowed_component(self):
181+ self.assertTrue(allowed_component(MAIN, MAIN))
182+ self.assertFalse(allowed_component(MAIN, UNIVERSE))
183+ self.assertFalse(allowed_component(MAIN, MULTIVERSE))
184+ self.assertFalse(allowed_component(MAIN, RESTRICTED))
185+
186+ self.assertTrue(allowed_component(RESTRICTED, MAIN))
187+ self.assertFalse(allowed_component(RESTRICTED, UNIVERSE))
188+ self.assertFalse(allowed_component(RESTRICTED, MULTIVERSE))
189+ self.assertTrue(allowed_component(RESTRICTED, RESTRICTED))
190+
191+ self.assertTrue(allowed_component(UNIVERSE, MAIN))
192+ self.assertTrue(allowed_component(UNIVERSE, UNIVERSE))
193+ self.assertFalse(allowed_component(UNIVERSE, MULTIVERSE))
194+ self.assertFalse(allowed_component(UNIVERSE, RESTRICTED))
195+
196+ self.assertTrue(allowed_component(MULTIVERSE, MAIN))
197+ self.assertTrue(allowed_component(MULTIVERSE, UNIVERSE))
198+ self.assertTrue(allowed_component(MULTIVERSE, MULTIVERSE))
199+ self.assertTrue(allowed_component(MULTIVERSE, RESTRICTED))
200+
201+
202+if __name__ == '__main__':
203+ unittest.main()

Subscribers

People subscribed via source and target branches