Merge lp:~rvb/launchpad/bug-869221 into lp:launchpad

Proposed by Raphaël Badin
Status: Merged
Approved by: Raphaël Badin
Approved revision: no longer in the source branch.
Merged at revision: 14121
Proposed branch: lp:~rvb/launchpad/bug-869221
Merge into: lp:launchpad
Diff against target: 171 lines (+77/-11)
4 files modified
lib/lp/registry/stories/webservice/xx-derivedistroseries.txt (+3/-0)
lib/lp/registry/tests/test_initderiveddistroseries.py (+5/-3)
lib/lp/soyuz/scripts/initialize_distroseries.py (+28/-3)
lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py (+41/-5)
To merge this branch: bzr merge lp:~rvb/launchpad/bug-869221
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+78548@code.launchpad.net

Commit message

[r=julian-edwards][bug=869221][incr] Raise a proper error when a derived series won't be able to have an architecture to build architecture independent binaries.

Description of the change

Before that branch, the arch independent builder for the derived series was simply taken from the first parent, no question asked. This is obviously a problem if the architecture in question was not among the architectures selected for the derived series.

This branch fixes that:
- In the case of multiple parents, we try to find a candidate for the child's nominatedarch.arch_tag by computing the intersection between the list of the parents architecture indep builders and the selected architectures;
- If this list is empty a proper error is raised.

A following branch will force the user to include a proper architecture in the list of the selected archtectures on the +initseries.

= Tests =

./bin/test -vvc test_initialize_distroseries test_multiple_parents_child_nominatedarchindep
./bin/test -vvc test_initialize_distroseries test_multiple_parents_no_child_nominatedarchindep

= QA =

*Test 1*
Initialize a series with architectures 'a' and 'b' ('b' being the arch indep one). Only select architecture 'a' for the child. The init job should error with the proper error message: "The distroseries has no architectures selected to build architecture independent binaries."

*Test 2*
Initialize a series from 2 parents: p1 and p2, p1 having two archtectures 'a' and 'b' ('b' being the arch indep one) and p2 having one architecture 'a' ('a' being - obviously - the arch indep one). Then initialize a child with only architecture 'a'. This should succeed and the nominatedarchindep for the resulting child should be 'a'.

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :

19 + if (len(potential_nominated_arches) == 0):
20 + raise InitializationError(
21 + ("The distroseries has no architectures selected to "
22 + "build architecture independent binaries."))

Nit - too many parentheses here, on all four lines :)

Everything else looks great, thanks!

review: Approve
Revision history for this message
Raphaël Badin (rvb) wrote :

> 19 + if (len(potential_nominated_arches) == 0):
> 20 + raise InitializationError(
> 21 + ("The distroseries has no architectures selected to "
> 22 + "build architecture independent binaries."))
>
> Nit - too many parentheses here, on all four lines :)

Fixed.

> Everything else looks great, thanks!

Thanks for the review!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/registry/stories/webservice/xx-derivedistroseries.txt'
--- lib/lp/registry/stories/webservice/xx-derivedistroseries.txt 2011-06-09 10:50:25 +0000
+++ lib/lp/registry/stories/webservice/xx-derivedistroseries.txt 2011-10-07 16:16:48 +0000
@@ -11,11 +11,14 @@
11 >>> from lp.testing.sampledata import ADMIN_EMAIL11 >>> from lp.testing.sampledata import ADMIN_EMAIL
12 >>> from canonical.launchpad.testing.pages import webservice_for_person12 >>> from canonical.launchpad.testing.pages import webservice_for_person
13 >>> from canonical.launchpad.webapp.interfaces import OAuthPermission13 >>> from canonical.launchpad.webapp.interfaces import OAuthPermission
14 >>> from zope.security.proxy import removeSecurityProxy
1415
15 >>> login(ADMIN_EMAIL)16 >>> login(ADMIN_EMAIL)
1617
17 >>> soyuz_team = factory.makeTeam(name='soyuz-team')18 >>> soyuz_team = factory.makeTeam(name='soyuz-team')
18 >>> parent_series = factory.makeDistroSeries(name="parentseries")19 >>> parent_series = factory.makeDistroSeries(name="parentseries")
20 >>> arch = factory.makeDistroArchSeries(distroseries=parent_series)
21 >>> removeSecurityProxy(parent_series).nominatedarchindep = arch
19 >>> child_series = factory.makeDistroSeries(name='child1')22 >>> child_series = factory.makeDistroSeries(name='child1')
20 >>> child_series_with_parent = factory.makeDistroSeries(23 >>> child_series_with_parent = factory.makeDistroSeries(
21 ... name='child-with-parent')24 ... name='child-with-parent')
2225
=== modified file 'lib/lp/registry/tests/test_initderiveddistroseries.py'
--- lib/lp/registry/tests/test_initderiveddistroseries.py 2011-08-22 11:39:17 +0000
+++ lib/lp/registry/tests/test_initderiveddistroseries.py 2011-10-07 16:16:48 +0000
@@ -42,6 +42,8 @@
42 def setUp(self):42 def setUp(self):
43 super(TestDeriveDistroSeries, self).setUp()43 super(TestDeriveDistroSeries, self).setUp()
44 self.parent = self.factory.makeDistroSeries()44 self.parent = self.factory.makeDistroSeries()
45 arch = self.factory.makeDistroArchSeries(distroseries=self.parent)
46 removeSecurityProxy(self.parent).nominatedarchindep = arch
45 self.child = self.factory.makeDistroSeries()47 self.child = self.factory.makeDistroSeries()
46 removeSecurityProxy(self.child).driver = self.factory.makePerson()48 removeSecurityProxy(self.child).driver = self.factory.makePerson()
47 login_person(self.child.driver)49 login_person(self.child.driver)
@@ -187,11 +189,11 @@
187 res = self.create2archParentAndSource(packages={'p1': '1.1'})189 res = self.create2archParentAndSource(packages={'p1': '1.1'})
188 parent, parent_das, parent_das2, source = res190 parent, parent_das, parent_das2, source = res
189 # Create builds for the architecture of parent_das2.191 # Create builds for the architecture of parent_das2.
190 source.createMissingBuilds(architectures_available=[parent_das2])192 source.createMissingBuilds(architectures_available=[parent_das])
191 child = self.factory.makeDistroSeries(193 child = self.factory.makeDistroSeries(
192 distribution=parent.distribution, previous_series=parent)194 distribution=parent.distribution, previous_series=parent)
193195
194 # Initialize only with parent_das's architecture. The build is196 # Initialize only with parent_das2's architecture. The build is
195 # in the other architecture so no exception should be raised.197 # in the other architecture so no exception should be raised.
196 child.initDerivedDistroSeries(198 child.initDerivedDistroSeries(
197 child.driver, [parent.id], (parent_das.architecturetag, ), ())199 child.driver, [parent.id], (parent_das2.architecturetag, ), ())
198200
=== modified file 'lib/lp/soyuz/scripts/initialize_distroseries.py'
--- lib/lp/soyuz/scripts/initialize_distroseries.py 2011-10-03 09:28:45 +0000
+++ lib/lp/soyuz/scripts/initialize_distroseries.py 2011-10-07 16:16:48 +0000
@@ -157,11 +157,22 @@
157 ".").format(157 ".").format(
158 child=self.distroseries))158 child=self.distroseries))
159 self._checkParents()159 self._checkParents()
160 self._checkArchindep()
160 for parent in self.derivation_parents:161 for parent in self.derivation_parents:
161 self._checkBuilds(parent)162 self._checkBuilds(parent)
162 self._checkQueue(parent)163 self._checkQueue(parent)
163 self._checkSeries()164 self._checkSeries()
164165
166 def _checkArchindep(self):
167 # Check that the child distroseries has an architecture to
168 # build architecture independent binaries.
169 potential_nominated_arches = self._potential_nominated_arches(
170 self.derivation_parents)
171 if len(potential_nominated_arches) == 0:
172 raise InitializationError(
173 "The distroseries has no architectures selected to "
174 "build architecture independent binaries.")
175
165 def _checkPublisherConfig(self):176 def _checkPublisherConfig(self):
166 """A series cannot be initialized if it has no publisher config177 """A series cannot be initialized if it has no publisher config
167 set up.178 set up.
@@ -365,9 +376,23 @@
365 """ % (sqlvalues(self.distroseries, self.distroseries.owner)376 """ % (sqlvalues(self.distroseries, self.distroseries.owner)
366 + (das_filter, )))377 + (das_filter, )))
367 self._store.flush()378 self._store.flush()
368 # Take nominatedarchindep from the first parent.379 # Select the arch-indep builder from the intersection between
369 self.distroseries.nominatedarchindep = self.distroseries[380 # the selected architectures and the list of the parent's
370 self.derivation_parents[0].nominatedarchindep.architecturetag]381 # arch-indep builders.
382 arch_tag = self._potential_nominated_arches(
383 self.derivation_parents).pop()
384 self.distroseries.nominatedarchindep = self.distroseries[arch_tag]
385
386 def _potential_nominated_arches(self, parent_list):
387 parent_indep_archtags = set(
388 parent.nominatedarchindep.architecturetag
389 for parent in parent_list
390 if parent.nominatedarchindep is not None)
391
392 if len(self.arches) == 0:
393 return parent_indep_archtags
394 else:
395 return parent_indep_archtags.intersection(self.arches)
371396
372 def _copy_packages(self):397 def _copy_packages(self):
373 # Perform the copies398 # Perform the copies
374399
=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py 2011-10-03 09:28:45 +0000
+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py 2011-10-07 16:16:48 +0000
@@ -259,7 +259,7 @@
259 parent, parent_das, parent_das2, source = res259 parent, parent_das, parent_das2, source = res
260 # Create builds for the architecture of parent_das2.260 # Create builds for the architecture of parent_das2.
261 source.createMissingBuilds(architectures_available=[parent_das2])261 source.createMissingBuilds(architectures_available=[parent_das2])
262 # Initialize only with parent_das2's architecture.262 # Initialize only with parent_das's architecture.
263 child = self.factory.makeDistroSeries()263 child = self.factory.makeDistroSeries()
264 ids = InitializeDistroSeries(264 ids = InitializeDistroSeries(
265 child, [parent.id], arches=[parent_das2.architecturetag])265 child, [parent.id], arches=[parent_das2.architecturetag])
@@ -293,13 +293,13 @@
293 # architecture we're initializing with, IDS will succeed.293 # architecture we're initializing with, IDS will succeed.
294 res = self.create2archParentAndSource(packages={'p1': '1.1'})294 res = self.create2archParentAndSource(packages={'p1': '1.1'})
295 parent, parent_das, parent_das2, source = res295 parent, parent_das, parent_das2, source = res
296 # Create builds for the architecture of parent_das2.296 # Create builds for the architecture of parent_das.
297 source.createMissingBuilds(architectures_available=[parent_das2])297 source.createMissingBuilds(architectures_available=[parent_das])
298 # Initialize only with parent_das's architecture.298 # Initialize only with parent_das2's architecture.
299 child = self.factory.makeDistroSeries(299 child = self.factory.makeDistroSeries(
300 distribution=parent.distribution, previous_series=parent)300 distribution=parent.distribution, previous_series=parent)
301 ids = InitializeDistroSeries(301 ids = InitializeDistroSeries(
302 child, arches=[parent_das.architecturetag])302 child, arches=[parent_das2.architecturetag])
303303
304 # No error is raised because we're initializing only the architecture304 # No error is raised because we're initializing only the architecture
305 # which has no pending builds in it.305 # which has no pending builds in it.
@@ -1383,3 +1383,39 @@
1383 self.assertEqual([], self.getWaitingJobs(child, 'p2', prev_parent2))1383 self.assertEqual([], self.getWaitingJobs(child, 'p2', prev_parent2))
1384 self.assertNotEqual([], self.getWaitingJobs(child, 'p1', parent3))1384 self.assertNotEqual([], self.getWaitingJobs(child, 'p1', parent3))
1385 self.assertEqual([], self.getWaitingJobs(child, 'p3', parent3))1385 self.assertEqual([], self.getWaitingJobs(child, 'p3', parent3))
1386
1387 def test_multiple_parents_child_nominatedarchindep(self):
1388 # If the list of the selected architectures and the list of the
1389 # nominatedarchindep for all the parent intersect, the child's
1390 # nominatedarchindep is taken from the intersection of the two
1391 # lists.
1392 parent1, unused = self.setupParent(
1393 packages={}, arch_tag='i386')
1394 parent2, unused = self.setupParent(
1395 packages={}, arch_tag='amd64')
1396 child = self._fullInitialize(
1397 [parent1, parent2],
1398 arches=[parent2.nominatedarchindep.architecturetag])
1399 self.assertEqual(
1400 child.nominatedarchindep.architecturetag,
1401 parent2.nominatedarchindep.architecturetag)
1402
1403 def test_multiple_parents_no_child_nominatedarchindep(self):
1404 # If the list of the selected architectures and the list of the
1405 # nominatedarchindep for all the parents don't intersect, an
1406 # error is raised because it means that the child won't have an
1407 # architecture to build architecture independent binaries.
1408 parent1, unused = self.setupParent(
1409 packages={}, arch_tag='i386')
1410 self.setupDas(parent1, 'hppa', 'powerpc')
1411 parent2, unused = self.setupParent(
1412 packages={}, arch_tag='amd64')
1413 child = self.factory.makeDistroSeries()
1414 ids = InitializeDistroSeries(
1415 child, [parent1.id, parent2.id],
1416 arches=['powerpc'])
1417 self.assertRaisesWithContent(
1418 InitializationError,
1419 ("The distroseries has no architectures selected to "
1420 "build architecture independent binaries."),
1421 ids.check)