launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #17851
[Merge] lp:~wgrant/launchpad/xbia-refactor into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/xbia-refactor into lp:launchpad.
Commit message:
Refactor build creation so buildarch and its tests can avoid the DB.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/xbia-refactor/+merge/249295
Refactor build creation so buildarch and its tests can avoid the DB. Makes things a bit less painfully slow and paves the way for the implementation of Build-Indep-Architecture.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/xbia-refactor into lp:launchpad.
=== modified file 'lib/lp/soyuz/adapters/buildarch.py'
--- lib/lp/soyuz/adapters/buildarch.py 2014-11-06 05:01:05 +0000
+++ lib/lp/soyuz/adapters/buildarch.py 2015-02-11 10:10:26 +0000
@@ -8,7 +8,6 @@
]
-from operator import attrgetter
import os
import subprocess
@@ -29,63 +28,37 @@
return self._matches[(arch, wildcard)]
def findAllMatches(self, arches, wildcards):
- return [arch for arch in arches for wildcard in wildcards
- if self.match(arch, wildcard)]
+ return list(sorted(set(
+ arch for arch in arches for wildcard in wildcards
+ if self.match(arch, wildcard))))
dpkg_architecture = DpkgArchitectureCache()
-def determine_architectures_to_build(hintlist, archive, distroseries,
- legal_archseries, need_arch_indep):
- """Return a list of architectures for which this publication should build.
-
- This function answers the question: given a list of architectures and
- an archive, what architectures should we build it for? It takes a set of
- legal distroarchseries and the distribution series for which we are
- building.
-
- For PPA publications we only consider architectures supported by PPA
- subsystem (`DistroArchSeries`.supports_virtualized flag).
-
- :param: hintlist: A string of the architectures this source package
+def determine_architectures_to_build(hintlist, valid_archs,
+ nominated_arch_indep, need_arch_indep):
+ """Return a set of architectures to build.
+
+ :param hintlist: A string of the architectures this source package
specifies it builds for.
- :param: archive: The `IArchive` we are building into.
- :param: distroseries: the context `DistroSeries`.
- :param: legal_archseries: a list of all initialized `DistroArchSeries`
- to be considered.
- :return: a list of `DistroArchSeries` for which the source publication in
+ :param valid_archs: a list of all architecture tags that we can
+ create builds for.
+ :param nominated_arch_indep: a preferred architecture tag for
+ architecture-independent builds. May be None.
+ :return: a set of architecture tags for which the source publication in
question should be built.
"""
- # The 'PPA supported' flag only applies to virtualized archives
- if archive.require_virtualized:
- legal_archseries = [
- arch for arch in legal_archseries if arch.supports_virtualized]
- # Cope with no virtualization support at all. It usually happens when
- # a distroseries is created and initialized, by default no
- # architecture supports its. Distro-team might take some time to
- # decide which architecture will be allowed for PPAs and queue-builder
- # will continue to work meanwhile.
- if not legal_archseries:
- return []
-
- legal_arch_tags = set(
- arch.architecturetag for arch in legal_archseries if arch.enabled)
-
hint_archs = set(hintlist.split())
- build_tags = set(dpkg_architecture.findAllMatches(
- legal_arch_tags, hint_archs))
+ build_archs = set(
+ dpkg_architecture.findAllMatches(valid_archs, hint_archs))
# 'all' is only used as a last resort, to create an arch-indep build
# where no builds would otherwise exist.
- if need_arch_indep and len(build_tags) == 0 and 'all' in hint_archs:
- nominated_arch = distroseries.nominatedarchindep
- if nominated_arch in legal_archseries:
- build_tags = set([nominated_arch.architecturetag])
+ if need_arch_indep and len(build_archs) == 0 and 'all' in hint_archs:
+ if nominated_arch_indep in valid_archs:
+ return set([nominated_arch_indep])
else:
- build_tags = set()
+ return set()
- sorted_archseries = sorted(
- legal_archseries, key=attrgetter('architecturetag'))
- return [arch for arch in sorted_archseries
- if arch.architecturetag in build_tags]
+ return build_archs
=== modified file 'lib/lp/soyuz/adapters/tests/test_buildarch.py'
--- lib/lp/soyuz/adapters/tests/test_buildarch.py 2014-11-06 05:01:05 +0000
+++ lib/lp/soyuz/adapters/tests/test_buildarch.py 2015-02-11 10:10:26 +0000
@@ -3,48 +3,52 @@
__metaclass__ = type
-from lp.soyuz.adapters.buildarch import determine_architectures_to_build
-from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
-from lp.testing import TestCaseWithFactory
-from lp.testing.layers import LaunchpadZopelessLayer
-
-
-class TestDetermineArchitecturesToBuild(TestCaseWithFactory):
+from lp.soyuz.adapters.buildarch import (
+ determine_architectures_to_build,
+ DpkgArchitectureCache,
+ )
+from lp.testing import TestCase
+
+
+class TestDpkgArchitectureCache(TestCase):
+
+ def test_multiple(self):
+ self.assertContentEqual(
+ ['amd64', 'armhf'],
+ DpkgArchitectureCache().findAllMatches(
+ ['amd64', 'i386', 'armhf'], ['amd64', 'armhf']))
+
+ def test_any(self):
+ self.assertContentEqual(
+ ['amd64', 'i386', 'kfreebsd-amd64'],
+ DpkgArchitectureCache().findAllMatches(
+ ['amd64', 'i386', 'kfreebsd-amd64'], ['any']))
+
+ def test_all(self):
+ self.assertContentEqual(
+ [],
+ DpkgArchitectureCache().findAllMatches(
+ ['amd64', 'i386', 'kfreebsd-amd64'], ['all']))
+
+ def test_partial_wildcards(self):
+ self.assertContentEqual(
+ ['amd64', 'i386', 'kfreebsd-amd64'],
+ DpkgArchitectureCache().findAllMatches(
+ ['amd64', 'i386', 'kfreebsd-amd64', 'kfreebsd-i386'],
+ ['linux-any', 'any-amd64']))
+
+
+class TestDetermineArchitecturesToBuild(TestCase):
"""Test that determine_architectures_to_build correctly interprets hints.
"""
- layer = LaunchpadZopelessLayer
-
- def setUp(self):
- super(TestDetermineArchitecturesToBuild, self).setUp()
- self.publisher = SoyuzTestPublisher()
- self.publisher.prepareBreezyAutotest()
- armel = self.factory.makeProcessor('armel', 'armel', 'armel')
- self.publisher.breezy_autotest.newArch(
- 'armel', armel, False, self.publisher.person)
- self.publisher.addFakeChroots()
-
- def assertArchitecturesToBuild(self, expected_arch_tags, pub,
- allowed_arch_tags=None):
+ def assertArchsForHint(self, hint_string, expected_arch_tags,
+ allowed_arch_tags=None):
if allowed_arch_tags is None:
- allowed_archs = self.publisher.breezy_autotest.architectures
- else:
- allowed_archs = [
- arch for arch in self.publisher.breezy_autotest.architectures
- if arch.architecturetag in allowed_arch_tags]
- architectures = determine_architectures_to_build(
- pub.sourcepackagerelease.architecturehintlist, pub.archive,
- self.publisher.breezy_autotest, allowed_archs, True)
- self.assertContentEqual(
- expected_arch_tags, [a.architecturetag for a in architectures])
-
- def assertArchsForHint(self, hint_string, expected_arch_tags,
- allowed_arch_tags=None, sourcename=None):
- """Assert that the given hint resolves to the expected archtags."""
- pub = self.publisher.getPubSource(
- sourcename=sourcename, architecturehintlist=hint_string)
- self.assertArchitecturesToBuild(
- expected_arch_tags, pub, allowed_arch_tags=allowed_arch_tags)
+ allowed_arch_tags = ['armel', 'hppa', 'i386']
+ arch_tags = determine_architectures_to_build(
+ hint_string, allowed_arch_tags, 'i386', True)
+ self.assertContentEqual(expected_arch_tags, arch_tags)
def test_single_architecture(self):
# A hint string with a single arch resolves to just that arch.
@@ -112,17 +116,6 @@
# it anyway.
self.assertArchsForHint('any-any', ['armel', 'hppa', 'i386'])
- def test_disabled_architectures_omitted(self):
- # Disabled architectures are not buildable, so are excluded.
- self.publisher.breezy_autotest['hppa'].enabled = False
- self.assertArchsForHint('any', ['armel', 'i386'])
-
- def test_virtualized_archives_have_only_virtualized_archs(self):
- # For archives which must build on virtual builders, only
- # virtual archs are returned.
- self.publisher.breezy_autotest.main_archive.require_virtualized = True
- self.assertArchsForHint('any', ['i386'])
-
def test_no_all_builds_when_nominatedarchindep_not_permitted(self):
# Some archives (eg. armel rebuilds) don't want arch-indep
# builds. If the nominatedarchindep architecture (normally
=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
--- lib/lp/soyuz/model/binarypackagebuild.py 2014-11-07 12:05:37 +0000
+++ lib/lp/soyuz/model/binarypackagebuild.py 2015-02-11 10:10:26 +0000
@@ -1385,9 +1385,16 @@
"""
# Return all distroarches with unrestricted processors or with
# processors the archive is explicitly associated with.
- return [distroarch for distroarch in available_archs
- if not distroarch.processor.restricted or
- distroarch.processor in archive.enabled_restricted_processors]
+ return [
+ das for das in available_archs
+ if (
+ das.enabled
+ and (
+ not das.processor.restricted
+ or das.processor in archive.enabled_restricted_processors)
+ and (
+ das.supports_virtualized
+ or not archive.require_virtualized))]
def createForSource(self, sourcepackagerelease, archive, distroseries,
pocket, architectures_available=None, logger=None):
@@ -1421,14 +1428,21 @@
# For an architecturehintlist of just 'all', this will
# be the current nominatedarchindep if need_arch_indep,
# otherwise nothing.
- if architectures_available is None:
- architectures_available = list(
- distroseries.buildable_architectures)
- architectures_available = self._getAllowedArchitectures(
- archive, architectures_available)
- candidate_architectures = determine_architectures_to_build(
- sourcepackagerelease.architecturehintlist, archive, distroseries,
- architectures_available, need_arch_indep)
+ valid_archs = list(
+ architectures_available or distroseries.buildable_architectures)
+ valid_archs = self._getAllowedArchitectures(archive, valid_archs)
+ nominated_arch_indep_tag = (
+ distroseries.nominatedarchindep.architecturetag
+ if distroseries.nominatedarchindep else None)
+
+ # Filter the valid archs against the hint list.
+ candidate_arch_tags = determine_architectures_to_build(
+ sourcepackagerelease.architecturehintlist,
+ [das.architecturetag for das in valid_archs],
+ nominated_arch_indep_tag, need_arch_indep)
+ candidate_architectures = set(
+ das for das in valid_archs
+ if das.architecturetag in candidate_arch_tags)
# Filter out any architectures for which we earlier found sufficient
# builds.
=== modified file 'lib/lp/soyuz/tests/test_build_set.py'
--- lib/lp/soyuz/tests/test_build_set.py 2014-11-06 05:20:01 +0000
+++ lib/lp/soyuz/tests/test_build_set.py 2015-02-11 10:10:26 +0000
@@ -236,6 +236,73 @@
self.builds[1].distro_arch_series))
+class TestGetAllowedArchitectures(TestCaseWithFactory):
+ """Tests for _getAllowedArchitectures."""
+
+ layer = ZopelessDatabaseLayer
+
+ def setUp(self):
+ super(TestGetAllowedArchitectures, self).setUp()
+ self.avr = self.factory.makeProcessor(name="avr2001")
+ self.sparc = self.factory.makeProcessor(name="sparc64")
+ self.distroseries = self.factory.makeDistroSeries()
+ for name, arch in (('avr', self.avr), ('sparc', self.sparc)):
+ self.factory.makeDistroArchSeries(
+ architecturetag=name, processor=arch,
+ distroseries=self.distroseries, supports_virtualized=True)
+ self.archive = self.factory.makeArchive(
+ distribution=self.distroseries.distribution)
+
+ def test_normal(self):
+ self.assertContentEqual(
+ [self.distroseries['sparc'], self.distroseries['avr']],
+ BinaryPackageBuildSet()._getAllowedArchitectures(
+ self.archive, self.distroseries.architectures))
+
+ def test_restricted(self):
+ # Restricted architectures aren't returned by default.
+ self.avr.restricted = True
+ self.assertContentEqual(
+ [self.distroseries['sparc']],
+ BinaryPackageBuildSet()._getAllowedArchitectures(
+ self.archive, self.distroseries.architectures))
+
+ def test_restricted_override(self):
+ # Restricted architectures are returned if allowed by the archive.
+ self.avr.restricted = True
+ getUtility(IArchiveArchSet).new(self.archive, self.avr)
+ self.assertContentEqual(
+ [self.distroseries['sparc'], self.distroseries['avr']],
+ BinaryPackageBuildSet()._getAllowedArchitectures(
+ self.archive, self.distroseries.architectures))
+
+ def test_disabled_architectures_omitted(self):
+ # Disabled architectures are not buildable, so are excluded.
+ self.distroseries['sparc'].enabled = False
+ self.assertContentEqual(
+ [self.distroseries['avr']],
+ BinaryPackageBuildSet()._getAllowedArchitectures(
+ self.archive, self.distroseries.architectures))
+
+ def test_virt_archives_have_only_virt_archs(self):
+ # For archives which must build on virtual builders, only
+ # virtual archs are returned.
+ self.distroseries['sparc'].supports_virtualized = False
+ self.assertContentEqual(
+ [self.distroseries['avr']],
+ BinaryPackageBuildSet()._getAllowedArchitectures(
+ self.archive, self.distroseries.architectures))
+
+ def test_nonvirt_archives_have_only_all_archs(self):
+ # Non-virtual archives can build on all unrestricted architectures.
+ self.distroseries['sparc'].supports_virtualized = False
+ self.archive.require_virtualized = False
+ self.assertContentEqual(
+ [self.distroseries['sparc'], self.distroseries['avr']],
+ BinaryPackageBuildSet()._getAllowedArchitectures(
+ self.archive, self.distroseries.architectures))
+
+
class BuildRecordCreationTests(TestNativePublishingBase):
"""Test the creation of build records."""
@@ -302,38 +369,6 @@
del success_map[build.distro_arch_series.architecturetag]
self.assertContentEqual([], success_map)
- def test__getAllowedArchitectures_restricted(self):
- """Test _getAllowedArchitectures doesn't return unrestricted
- archs.
-
- For a normal archive, only unrestricted architectures should
- be used.
- """
- self.avr.restricted = True
- available_archs = [
- self.distroseries['sparc'], self.distroseries['avr']]
- pubrec = self.getPubSource(architecturehintlist='any')
- self.assertEqual(
- [self.distroseries['sparc']],
- BinaryPackageBuildSet()._getAllowedArchitectures(
- pubrec.archive, available_archs))
-
- def test__getAllowedArchitectures_restricted_override(self):
- """Test _getAllowedArchitectures honors overrides of restricted archs.
-
- Restricted architectures should only be allowed if there is
- an explicit ArchiveArch association with the archive.
- """
- self.avr.restricted = True
- available_archs = [
- self.distroseries['sparc'], self.distroseries['avr']]
- getUtility(IArchiveArchSet).new(self.archive, self.avr)
- pubrec = self.getPubSource(architecturehintlist='any')
- self.assertEqual(
- [self.distroseries['sparc'], self.distroseries['avr']],
- BinaryPackageBuildSet()._getAllowedArchitectures(
- pubrec.archive, available_archs))
-
def test_createForSource_restricts_any(self):
"""createForSource() should limit builds targeted at 'any'
architecture to those allowed for the archive.
Follow ups