← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/move-SPR-build-methods into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/move-SPR-build-methods into lp:launchpad.

Commit message:
Replace SourcePackageRelease.getBuildByArch with BinaryPackageBuildSet.getBySourceAndLocation.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/move-SPR-build-methods/+merge/240224

Replace SourcePackageRelease.getBuildByArch with BinaryPackageBuildSet.getBySourceAndLocation.
-- 
https://code.launchpad.net/~wgrant/launchpad/move-SPR-build-methods/+merge/240224
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/move-SPR-build-methods into lp:launchpad.
=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
--- lib/lp/archiveuploader/nascentuploadfile.py	2013-10-10 18:47:16 +0000
+++ lib/lp/archiveuploader/nascentuploadfile.py	2014-10-31 08:42:03 +0000
@@ -56,6 +56,7 @@
     PackagePublishingPriority,
     PackageUploadCustomFormat,
     )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.section import ISectionSet
@@ -846,8 +847,8 @@
         dar = self.policy.distroseries[self.archtag]
 
         # Check if there's a suitable existing build.
-        build = sourcepackagerelease.getBuildByArch(
-            dar, self.policy.archive)
+        build = getUtility(IBinaryPackageBuildSet).getBySourceAndLocation(
+            sourcepackagerelease, self.policy.archive, dar)
         if build is not None:
             build.updateStatus(BuildStatus.FULLYBUILT)
             self.logger.debug("Updating build for %s: %s" % (
@@ -855,9 +856,9 @@
         else:
             # No luck. Make one.
             # Usually happen for security binary uploads.
-            build = sourcepackagerelease.createBuild(
-                dar, self.policy.pocket, self.policy.archive,
-                status=BuildStatus.FULLYBUILT)
+            build = getUtility(IBinaryPackageBuildSet).new(
+                sourcepackagerelease, self.policy.archive, dar,
+                self.policy.pocket, status=BuildStatus.FULLYBUILT)
             self.logger.debug("Build %s created" % build.id)
         return build
 

=== modified file 'lib/lp/archiveuploader/tests/nascentupload.txt'
--- lib/lp/archiveuploader/tests/nascentupload.txt	2012-12-26 01:32:19 +0000
+++ lib/lp/archiveuploader/tests/nascentupload.txt	2014-10-31 08:42:03 +0000
@@ -558,9 +558,11 @@
 
 Build creation is done based on the SourcePackageRelease object, step 5:
 
-    >>> multibar_build = multibar_spr.createBuild(
-    ...     hoary['i386'], PackagePublishingPocket.RELEASE,
-    ...     multibar_src_queue.archive)
+    >>> from lp.soyuz.interfaces.binarypackagebuild import (
+    ...     IBinaryPackageBuildSet)
+    >>> multibar_build = getUtility(IBinaryPackageBuildSet).new(
+    ...     multibar_spr, multibar_src_queue.archive, hoary['i386'],
+    ...     PackagePublishingPocket.RELEASE)
 
     >>> multibar_build.status.name
     'NEEDSBUILD'

=== modified file 'lib/lp/archiveuploader/tests/test_buildduploads.py'
--- lib/lp/archiveuploader/tests/test_buildduploads.py	2013-09-13 06:20:49 +0000
+++ lib/lp/archiveuploader/tests/test_buildduploads.py	2014-10-31 08:42:03 +0000
@@ -20,6 +20,7 @@
     PackagePublishingStatus,
     PackageUploadStatus,
     )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.processor import IProcessorSet
 from lp.soyuz.interfaces.publishing import IPublishingSet
 from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
@@ -139,9 +140,9 @@
     def _createBuild(self, archtag):
         """Create a build record attached to the base source."""
         spr = self.source_queue.sources[0].sourcepackagerelease
-        build = spr.createBuild(
-            distro_arch_series=self.distroseries[archtag],
-            pocket=self.pocket, archive=self.distroseries.main_archive)
+        build = getUtility(IBinaryPackageBuildSet).new(
+            spr, self.distroseries.main_archive, self.distroseries[archtag],
+            self.pocket)
         self.layer.txn.commit()
         return build
 

=== modified file 'lib/lp/archiveuploader/tests/test_ppauploadprocessor.py'
--- lib/lp/archiveuploader/tests/test_ppauploadprocessor.py	2014-08-21 03:00:46 +0000
+++ lib/lp/archiveuploader/tests/test_ppauploadprocessor.py	2014-10-31 08:42:03 +0000
@@ -33,6 +33,7 @@
     PackageUploadStatus,
     SourcePackageFormat,
     )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.queue import NonBuildableSourceUploadError
 from lp.soyuz.interfaces.sourcepackageformat import (
     ISourcePackageFormatSelectionSet,
@@ -420,9 +421,9 @@
 
         # Create a build record for source bar for breezy-i386
         # distroarchseries in cprov PPA.
-        build_bar_i386 = cprov_pub_bar.sourcepackagerelease.createBuild(
-            self.breezy['i386'], PackagePublishingPocket.RELEASE,
-            cprov.archive)
+        build_bar_i386 = getUtility(IBinaryPackageBuildSet).new(
+            cprov_pub_bar.sourcepackagerelease, cprov.archive,
+            self.breezy['i386'], PackagePublishingPocket.RELEASE)
 
         # Binary upload to the just-created build record.
         self.options.context = 'buildd'

=== modified file 'lib/lp/archiveuploader/tests/test_uploadprocessor.py'
--- lib/lp/archiveuploader/tests/test_uploadprocessor.py	2014-08-29 02:03:52 +0000
+++ lib/lp/archiveuploader/tests/test_uploadprocessor.py	2014-10-31 08:42:03 +0000
@@ -74,6 +74,7 @@
     )
 from lp.soyuz.interfaces.archive import IArchiveSet
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.packageset import IPackagesetSet
 from lp.soyuz.interfaces.publishing import (
@@ -839,9 +840,9 @@
         bar_copied_source = bar_source_pub.copyTo(
             breezy_autotest, PackagePublishingPocket.RELEASE,
             self.ubuntu.main_archive)
-        bar_copied_build = bar_copied_source.sourcepackagerelease.createBuild(
-            breezy_autotest_i386, PackagePublishingPocket.RELEASE,
-            self.ubuntu.main_archive)
+        bar_copied_build = getUtility(IBinaryPackageBuildSet).new(
+            bar_copied_source.sourcepackagerelease, self.ubuntu.main_archive,
+            breezy_autotest_i386, PackagePublishingPocket.RELEASE)
 
         # Re-upload the same 'bar-1.0-1' binary as if it was rebuilt
         # in breezy-autotest context.
@@ -1058,9 +1059,9 @@
         # Fudge a build for foocomm so that it's not in the partner archive.
         # We can then test that uploading a binary package must match the
         # build's archive.
-        foocomm_build = foocomm_spr.createBuild(
-            self.breezy['i386'], PackagePublishingPocket.RELEASE,
-            self.ubuntu.main_archive)
+        foocomm_build = getUtility(IBinaryPackageBuildSet).new(
+            foocomm_spr, self.ubuntu.main_archive, self.breezy['i386'],
+            PackagePublishingPocket.RELEASE)
         self.layer.txn.commit()
         upload_dir = self.queueUpload("foocomm_1.0-1_binary")
         build_uploadprocessor = self.getUploadProcessor(

=== modified file 'lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py'
--- lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py	2014-06-26 11:50:58 +0000
+++ lib/lp/buildmaster/tests/test_buildfarmjobbehaviour.py	2014-10-31 08:42:03 +0000
@@ -35,6 +35,7 @@
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.config import config
 from lp.services.log.logger import BufferLogger
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.processor import IProcessorSet
 from lp.testing import (
     TestCase,
@@ -100,9 +101,8 @@
         pocket = PackagePublishingPocket.RELEASE
         spr = self.factory.makeSourcePackageRelease(
             distroseries=distroseries, archive=archive)
-
-        return spr.createBuild(
-            distroarchseries=distroarchseries, pocket=pocket, archive=archive)
+        return getUtility(IBinaryPackageBuildSet).new(
+            spr, archive, distroarchseries, pocket)
 
     def test_getUploadDirLeaf(self):
         # getUploadDirLeaf returns the current time, followed by the build

=== modified file 'lib/lp/soyuz/browser/tests/archive-views.txt'
--- lib/lp/soyuz/browser/tests/archive-views.txt	2014-08-08 17:27:07 +0000
+++ lib/lp/soyuz/browser/tests/archive-views.txt	2014-10-31 08:42:03 +0000
@@ -389,9 +389,9 @@
     ...     IBinaryPackageBuildSet)
     >>> warty_hppa = getUtility(IDistributionSet)['ubuntu']['warty']['hppa']
     >>> source = view.filtered_sources[0]
-    >>> ignore = source.sourcepackagerelease.createBuild(
-    ...     distro_arch_series=warty_hppa, archive=view.context,
-    ...     pocket=source.pocket)
+    >>> ignore = getUtility(IBinaryPackageBuildSet).new(
+    ...     source.sourcepackagerelease, view.context, warty_hppa,
+    ...     source.pocket)
     >>> builds = getUtility(IBinaryPackageBuildSet).getBuildsForArchive(
     ...     view.context)
     >>> for build in builds:

=== modified file 'lib/lp/soyuz/browser/tests/distributionsourcepackagerelease-views.txt'
--- lib/lp/soyuz/browser/tests/distributionsourcepackagerelease-views.txt	2010-02-11 12:47:50 +0000
+++ lib/lp/soyuz/browser/tests/distributionsourcepackagerelease-views.txt	2014-10-31 08:42:03 +0000
@@ -126,11 +126,15 @@
     # Create extras builds for the testing DSPR.
     >>> login('foo.bar@xxxxxxxxxxxxx')
     >>> hoary_amd64 = hoary['amd64']
-    >>> unused = source.sourcepackagerelease.createBuild(
-    ...     hoary_amd64, release_pocket, stp.ubuntutest.main_archive)
+    >>> from lp.soyuz.interfaces.binarypackagebuild import (
+    ...     IBinaryPackageBuildSet)
+    >>> unused = getUtility(IBinaryPackageBuildSet).new(
+    ...     source.sourcepackagerelease, stp.ubuntutest.main_archive,
+    ...     hoary_amd64, release_pocket)
     >>> breezy_hppa = stp.breezy_autotest['hppa']
-    >>> unused = source.sourcepackagerelease.createBuild(
-    ...     breezy_hppa, release_pocket, stp.ubuntutest.main_archive)
+    >>> unused = getUtility(IBinaryPackageBuildSet).new(
+    ...     source.sourcepackagerelease, stp.ubuntutest.main_archive,
+    ...     breezy_hppa, release_pocket)
     >>> login(ANONYMOUS)
 
     >>> dspr_view = create_initialized_view(dspr, name="+index")

=== modified file 'lib/lp/soyuz/browser/tests/test_build_views.py'
--- lib/lp/soyuz/browser/tests/test_build_views.py	2013-12-04 07:07:04 +0000
+++ lib/lp/soyuz/browser/tests/test_build_views.py	2014-10-31 08:42:03 +0000
@@ -29,6 +29,7 @@
 from lp.soyuz.browser.build import BuildContextMenu
 from lp.soyuz.enums import ArchivePurpose
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.packageset import IPackagesetSet
 from lp.soyuz.model.queue import PackageUploadBuild
 from lp.testing import (
@@ -68,8 +69,9 @@
         # current_component used by the view returns None in that case.
         spph = self.factory.makeSourcePackagePublishingHistory()
         other_das = self.factory.makeDistroArchSeries()
-        build = spph.sourcepackagerelease.createBuild(
-            other_das, PackagePublishingPocket.RELEASE, spph.archive)
+        build = getUtility(IBinaryPackageBuildSet).new(
+            spph.sourcepackagerelease, spph.archive, other_das,
+            PackagePublishingPocket.RELEASE)
         view = create_initialized_view(build, name="+index")
         self.assertEqual('unknown', view.component_name)
 

=== modified file 'lib/lp/soyuz/doc/distroseriesqueue-translations.txt'
--- lib/lp/soyuz/doc/distroseriesqueue-translations.txt	2013-10-24 04:43:51 +0000
+++ lib/lp/soyuz/doc/distroseriesqueue-translations.txt	2014-10-31 08:42:03 +0000
@@ -77,9 +77,11 @@
 
 # Do the upload into the system.
 
-    >>> build = source_package_release.createBuild(
-    ...      dapper_amd64, PackagePublishingPocket.RELEASE,
-    ...      dapper.main_archive)
+    >>> from lp.soyuz.interfaces.binarypackagebuild import (
+    ...     IBinaryPackageBuildSet)
+    >>> build = getUtility(IBinaryPackageBuildSet).new(
+    ...     source_package_release, dapper.main_archive,
+    ...     dapper_amd64, PackagePublishingPocket.RELEASE)
 
     >>> buildd_policy = getPolicy(
     ...     name='buildd', distro='ubuntu', distroseries='dapper')

=== modified file 'lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt'
--- lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt	2012-11-21 07:19:09 +0000
+++ lib/lp/soyuz/doc/sourcepackagerelease-build-lookup.txt	2014-10-31 08:42:03 +0000
@@ -5,20 +5,19 @@
 
 = Creating & Looking for Build records =
 
-ISourcePackageRelease has the ability to create Build records,
-however it needs external support to treat architecturehintlist and
-Package-architecture-specific (P-a-s) information, see further
-information in buildd-queuebuilder.txt.
+IBinaryPackageBuildSet can create and look up build records.
 
-ISourcePackageRelease also provides a 'getBuildByArch' method which
-allows the application to lookup for Build records in a given
-DistroArchSeries and Archive.
+It provides a 'getBySourceAndLocation' method which allows the
+application to lookup for BinaryPackageBuild records for
+SourcePackageRelease in a given DistroArchSeries and Archive.
 
 To demonstrate this we need to define some variables.
 
     >>> from zope.component import getUtility
+    >>> from lp.registry.interfaces.distribution import IDistributionSet
     >>> from lp.services.librarian.interfaces import ILibraryFileAliasSet
-    >>> from lp.registry.interfaces.distribution import IDistributionSet
+    >>> from lp.soyuz.interfaces.binarypackagebuild import (
+    ...     IBinaryPackageBuildSet)
 
     >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
     >>> hoary = ubuntu.getSeries('hoary')
@@ -39,8 +38,8 @@
     ...    PackagePublishingPocket)
     >>> pocket_release = PackagePublishingPocket.RELEASE
 
-The base method createBuild() is able to create a build to a given
-distro_arch_series, pocket and archive.
+The base method BinaryPackageBuildSet.new() is able to create a build to
+a given distro_arch_series, pocket and archive.
 
 Build.status, by default is set to NEEDSBUILD, but you can
 optionally provide another status.
@@ -49,8 +48,10 @@
     >>> evo_release = hoary_evo_source['1.0'].sourcepackagerelease
 
     >>> from lp.buildmaster.enums import BuildStatus
-    >>> evo_build_i386 = evo_release.createBuild(
-    ...     hoary_i386, pocket_release, ubuntu.main_archive,
+    >>> from lp.soyuz.interfaces.binarypackagebuild import (
+    ...     IBinaryPackageBuildSet)
+    >>> evo_build_i386 = getUtility(IBinaryPackageBuildSet).new(
+    ...     evo_release, ubuntu.main_archive, hoary_i386, pocket_release,
     ...     status=BuildStatus.FULLYBUILT)
 
     >>> print evo_build_i386.status.name
@@ -62,18 +63,18 @@
     >>> print evo_build_i386.archive.displayname
     Primary Archive for Ubuntu Linux
 
-The build record can be retrieved via getBuildByArch on hoary/i386
-architecture.
+The build record can be retrieved on hoary/i386 architecture.
 
-    >>> test_build_i386 = evo_release.getBuildByArch(
-    ...     hoary_i386, ubuntu.main_archive)
+    >>> bpbs = getUtility(IBinaryPackageBuildSet)
+    >>> test_build_i386 = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, hoary_i386)
     >>> test_build_i386 == evo_build_i386
     True
 
 However a hoary/hppa build is not available.
 
-    >>> test_build_hppa = evo_release.getBuildByArch(
-    ...     hoary_hppa, ubuntu.main_archive)
+    >>> test_build_hppa = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, hoary_hppa)
     >>> print test_build_hppa
     None
 
@@ -106,8 +107,8 @@
 In practical terms it means that another build is not necessary in
 this context.
 
-    >>> breezy_autotest_build = evo_release.getBuildByArch(
-    ...     breezy_autotest_i386, ubuntu.main_archive)
+    >>> breezy_autotest_build = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, breezy_autotest_i386)
     >>> print breezy_autotest_build.title
     i386 build of evolution 1.0 in ubuntu hoary RELEASE
 
@@ -115,8 +116,8 @@
 == Sources with architecture-independent and specific binaries ==
 
 Even if the source package builds an architecture-independent package,
-no Build record will be returned by getBuildByArch() if arch-specific
-binary packages were not built (see bug #65712 for further
+no Build record will be returned by getBySourceAndLocation() if
+arch-specific binary packages were not built (see bug #65712 for further
 information).
 
 In order to be independent of the sampledata we will use the
@@ -147,8 +148,8 @@
 
 The build record for foo in hoary/i386 was created.
 
-    >>> test_build_i386 = foo_pub_src.sourcepackagerelease.getBuildByArch(
-    ...     hoary_i386, ubuntu.main_archive)
+    >>> test_build_i386 = bpbs.getBySourceAndLocation(
+    ...     foo_pub_src.sourcepackagerelease, ubuntu.main_archive, hoary_i386)
     >>> print test_build_i386.title
     i386 build of foo 1.0 in ubuntu hoary RELEASE
 
@@ -161,8 +162,8 @@
     foo-bin 1.0 in hoary i386
     foo-bin 1.0 in hoary hppa
 
-    >>> test_build_hppa = foo_pub_src.sourcepackagerelease.getBuildByArch(
-    ...     hoary_hppa, ubuntu.main_archive)
+    >>> test_build_hppa = bpbs.getBySourceAndLocation(
+    ...     foo_pub_src.sourcepackagerelease, ubuntu.main_archive, hoary_hppa)
     >>> print test_build_hppa
     None
 
@@ -180,8 +181,8 @@
 
 No suitable build will be found for it.
 
-    >>> test_build_i386_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_i386, cprov.archive)
+    >>> test_build_i386_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_i386)
     >>> print test_build_i386_ppa
     None
 
@@ -192,8 +193,9 @@
 versions, so the resulted binary will be influenced by the PPA
 contents at the time it was built.
 
-    >>> evo_build_i386_ppa = copy.sourcepackagerelease.createBuild(
-    ...     hoary_i386, pocket_release, cprov.archive)
+    >>> evo_build_i386_ppa = getUtility(IBinaryPackageBuildSet).new(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_i386,
+    ...     pocket_release)
 
     >>> evo_build_i386_ppa.status.name
     'NEEDSBUILD'
@@ -204,32 +206,32 @@
 The copied source build lookup in the PPA returns the build created in
 the PPA context, not the PRIMARY archive one.
 
-    >>> test_build_i386_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_i386, cprov.archive)
+    >>> test_build_i386_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_i386)
     >>> test_build_i386_ppa == evo_build_i386_ppa
     True
 
 As expected, the hoary/hppa build is still missing in both archives.
 
-    >>> test_build_hppa_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_hppa, cprov.archive)
+    >>> test_build_hppa_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_hppa)
     >>> print test_build_hppa_ppa
     None
 
 When we create a hoary/hppa build in the PPA context, it will continue
 to be missing in the PRIMARY archive context.
 
-    >>> evo_build_hppa_ppa = copy.sourcepackagerelease.createBuild(
-    ...     hoary_hppa, pocket_release, cprov.archive)
-
-    >>> test_build_hppa_ppa = copy.sourcepackagerelease.getBuildByArch(
-    ...     hoary_hppa, cprov.archive)
-
+    >>> evo_build_hppa_ppa = getUtility(IBinaryPackageBuildSet).new(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_hppa,
+    ...     pocket_release)
+
+    >>> test_build_hppa_ppa = bpbs.getBySourceAndLocation(
+    ...     copy.sourcepackagerelease, cprov.archive, hoary_hppa)
     >>> print test_build_hppa_ppa.title
     hppa build of evolution 1.0 in ubuntu hoary RELEASE
 
-    >>> test_build_hppa = evo_release.getBuildByArch(
-    ...     hoary_hppa, ubuntu.main_archive)
+    >>> test_build_hppa = bpbs.getBySourceAndLocation(
+    ...     evo_release, ubuntu.main_archive, hoary_hppa)
     >>> print test_build_hppa
     None
 
@@ -253,8 +255,8 @@
     ...     status=PackagePublishingStatus.PUBLISHED)
 
     >>> foo_source_release = foo_pub_src.sourcepackagerelease
-    >>> build_primary = foo_source_release.getBuildByArch(
-    ...     hoary_i386, ubuntu.main_archive)
+    >>> build_primary = bpbs.getBySourceAndLocation(
+    ...     foo_source_release, ubuntu.main_archive, hoary_i386)
 
     >>> print build_primary.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE
@@ -279,8 +281,8 @@
 bug #181736 report for previous mistakes in this area.
 
     >>> cprov_spr = cprov_src.sourcepackagerelease
-    >>> cprov_build = cprov_spr.getBuildByArch(
-    ...     hoary_i386, cprov.archive)
+    >>> cprov_build = bpbs.getBySourceAndLocation(
+    ...     cprov_spr, cprov.archive, hoary_i386)
 
     >>> print cprov_build.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE
@@ -305,8 +307,8 @@
 
     >>> copied_release = copy.sourcepackagerelease
     >>> breezy_autotest_i386 = breezy_autotest['i386']
-    >>> copied_build_candidate = copied_release.getBuildByArch(
-    ...     breezy_autotest_i386, cprov.archive)
+    >>> copied_build_candidate = bpbs.getBySourceAndLocation(
+    ...     copied_release, cprov.archive, breezy_autotest_i386)
     >>> print copied_build_candidate
     None
 
@@ -331,8 +333,8 @@
 
     >>> copied_source_release = copied_source.sourcepackagerelease
     >>> warty_i386 = warty['i386']
-    >>> copied_build_candidate = copied_source_release.getBuildByArch(
-    ...     warty_i386, cprov.archive)
+    >>> copied_build_candidate = bpbs.getBySourceAndLocation(
+    ...     copied_source_release, cprov.archive, warty_i386)
 
     >>> print copied_build_candidate.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE
@@ -360,8 +362,8 @@
 original build that happened in the primary archive.
 
     >>> mark_spr = mark_src.sourcepackagerelease
-    >>> mark_build = mark_spr.getBuildByArch(
-    ...     hoary_i386, mark.archive)
+    >>> mark_build = bpbs.getBySourceAndLocation(
+    ...     mark_spr, mark.archive, hoary_i386)
 
     >>> print mark_build.title
     i386 build of foo 0.1 in ubuntu hoary RELEASE

=== modified file 'lib/lp/soyuz/interfaces/binarypackagebuild.py'
--- lib/lp/soyuz/interfaces/binarypackagebuild.py	2014-10-31 03:12:58 +0000
+++ lib/lp/soyuz/interfaces/binarypackagebuild.py	2014-10-31 08:42:03 +0000
@@ -295,19 +295,15 @@
 class IBinaryPackageBuildSet(ISpecificBuildFarmJobSource):
     """Interface for BinaryPackageBuildSet"""
 
-    def new(distro_arch_series, source_package_release, processor,
-            archive, pocket, status=BuildStatus.NEEDSBUILD,
-            date_created=None, builder=None):
+    def new(source_package_release, archive, distro_arch_series, pocket,
+            status=BuildStatus.NEEDSBUILD, builder=None):
         """Create a new `IBinaryPackageBuild`.
 
-        :param distro_arch_series: An `IDistroArchSeries`.
         :param source_package_release: An `ISourcePackageRelease`.
-        :param processor: An `IProcessor`.
         :param archive: An `IArchive` in which context the build is built.
+        :param distro_arch_series: An `IDistroArchSeries`.
         :param pocket: An item of `PackagePublishingPocket`.
         :param status: A `BuildStatus` item indicating the builds status.
-        :param date_created: An optional datetime to ensure multiple builds
-            in the same transaction don't all get the same UTC_NOW.
         :param builder: An optional `IBuilder`.
         """
 
@@ -364,6 +360,16 @@
         :return: a list of `IBuild` records not target to PPA archives.
         """
 
+    def getBySourceAndLocation(sourcepackagerelease, archive,
+                               distroarchseries):
+        """Return build for the given source, archive and distroarchseries.
+
+        It looks for a build in any state registered *directly* for the
+        given distroarchseries and archive.
+
+        Returns None if a suitable build could not be found.
+        """
+
     def getStatusSummaryForBuilds(builds):
         """Return a summary of the build status for the given builds.
 

=== modified file 'lib/lp/soyuz/interfaces/packagecloner.py'
--- lib/lp/soyuz/interfaces/packagecloner.py	2013-09-10 06:28:26 +0000
+++ lib/lp/soyuz/interfaces/packagecloner.py	2014-10-31 08:42:03 +0000
@@ -16,8 +16,7 @@
     """Copies publishing history data across archives."""
 
     def clonePackages(origin, destination, distroarchseries_list=None,
-                    processors=None, sourcepackagenames=None,
-                    always_create=False):
+                    processors=None, sourcepackagenames=None):
         """Copy packages from origin to destination.
 
         Copies the source packages, as well as the binary packages for the
@@ -30,7 +29,6 @@
         :param processors: the processors that builds will be created for.
         :param sourcepackagenames: the source packages which are to be
             copied.
-        :param always_create: if builds should always be created.
         """
 
     def mergeCopy(origin, destination):

=== modified file 'lib/lp/soyuz/interfaces/sourcepackagerelease.py'
--- lib/lp/soyuz/interfaces/sourcepackagerelease.py	2014-06-11 15:40:51 +0000
+++ lib/lp/soyuz/interfaces/sourcepackagerelease.py	2014-10-31 08:42:03 +0000
@@ -174,25 +174,6 @@
         :return the corresponding `ILibraryFileAlias` if the file was found.
         """
 
-    def createBuild(distroarchseries, pocket, archive, processor=None,
-                    status=None):
-        """Create a build for a given distroarchseries/pocket/archive
-
-        If the processor isn't given, guess it from the distroarchseries.
-        If the status isn't given, use NEEDSBUILD.
-
-        Return the just created IBuild.
-        """
-
-    def getBuildByArch(distroarchseries, archive):
-        """Return build for the given distroarchseries/archive.
-
-        It looks for a build in any state registered *directly* for the
-        given distroarchseries and archive.
-
-        Returns None if a suitable build could not be found.
-        """
-
     def override(component=None, section=None, urgency=None):
         """Uniform method to override sourcepackagerelease attribute.
 

=== modified file 'lib/lp/soyuz/model/binarypackagebuild.py'
--- lib/lp/soyuz/model/binarypackagebuild.py	2014-10-31 03:17:04 +0000
+++ lib/lp/soyuz/model/binarypackagebuild.py	2014-10-31 08:42:03 +0000
@@ -24,6 +24,7 @@
     LeftJoin,
     Or,
     )
+from storm.info import ClassAlias
 from storm.locals import (
     Bool,
     DateTime,
@@ -893,27 +894,28 @@
 class BinaryPackageBuildSet(SpecificBuildFarmJobSourceMixin):
     implements(IBinaryPackageBuildSet)
 
-    def new(self, distro_arch_series, source_package_release, processor,
-            archive, pocket, status=BuildStatus.NEEDSBUILD,
-            date_created=None, builder=None):
+    def new(self, source_package_release, archive, distro_arch_series, pocket,
+            status=BuildStatus.NEEDSBUILD, builder=None):
         """See `IBinaryPackageBuildSet`."""
+        # Force the current timestamp instead of the default UTC_NOW for
+        # the transaction, avoid several row with same datecreated.
+        date_created = datetime.datetime.now(pytz.timezone('UTC'))
         # Create the BuildFarmJob for the new BinaryPackageBuild.
         build_farm_job = getUtility(IBuildFarmJobSource).new(
             BinaryPackageBuild.job_type, status, date_created, builder,
             archive)
-        binary_package_build = BinaryPackageBuild(
+        return BinaryPackageBuild(
             build_farm_job=build_farm_job,
             distro_arch_series=distro_arch_series,
             source_package_release=source_package_release,
-            archive=archive, pocket=pocket, status=status, processor=processor,
+            archive=archive, pocket=pocket, status=status,
+            processor=distro_arch_series.processor,
             virtualized=archive.require_virtualized, builder=builder,
             is_distro_archive=archive.is_main,
             distribution=distro_arch_series.distroseries.distribution,
             distro_series=distro_arch_series.distroseries,
-            source_package_name=source_package_release.sourcepackagename)
-        if date_created is not None:
-            binary_package_build.date_created = date_created
-        return binary_package_build
+            source_package_name=source_package_release.sourcepackagename,
+            date_created=date_created)
 
     def getByID(self, id):
         """See `IBinaryPackageBuildSet`."""
@@ -1150,6 +1152,90 @@
             Desc(BinaryPackageBuild.date_created), BinaryPackageBuild.id)
         return resultset
 
+    def _findBySourceAndLocation(self, sourcepackagerelease, archive,
+                                 distroseries):
+        """Find builds for a SourcePackageRelease by series and archive.
+
+        Looks for `BinaryPackageBuild` records for this source package
+        release, with publication records in the given distroseries.
+        There should be at most one of these per architecture.
+
+        :param distroseries: `DistroSeries` to look for.
+        :return: A dict mapping architecture tags (in string form,
+            e.g. 'i386') to `BinaryPackageBuild`s for that build.
+        """
+        # Avoid circular imports.
+        from lp.soyuz.model.distroarchseries import DistroArchSeries
+        from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
+
+        BuildDAS = ClassAlias(DistroArchSeries, 'BuildDAS')
+        PublishDAS = ClassAlias(DistroArchSeries, 'PublishDAS')
+
+        query = IStore(BinaryPackageBuild).find(
+            (BuildDAS.architecturetag, BinaryPackageBuild),
+            BinaryPackageBuild.source_package_release == sourcepackagerelease,
+            BinaryPackageRelease.buildID == BinaryPackageBuild.id,
+            BuildDAS.id == BinaryPackageBuild.distro_arch_series_id,
+            BinaryPackagePublishingHistory.binarypackagereleaseID ==
+                BinaryPackageRelease.id,
+            BinaryPackagePublishingHistory.archiveID == archive.id,
+            PublishDAS.id ==
+                BinaryPackagePublishingHistory.distroarchseriesID,
+            PublishDAS.distroseriesID == distroseries.id,
+            # Architecture-independent binary package releases are built
+            # in the nominated arch-indep architecture but published in
+            # all architectures.  This condition makes sure we consider
+            # only builds that have been published in their own
+            # architecture.
+            PublishDAS.architecturetag == BuildDAS.architecturetag)
+        results = list(query.config(distinct=True))
+        mapped_results = dict(results)
+        assert len(mapped_results) == len(results), (
+            "Found multiple build candidates per architecture: %s.  "
+            "This may mean that we have a serious problem in our DB model.  "
+            "Further investigation is required."
+            % [(tag, build.id) for tag, build in results])
+        return mapped_results
+
+    def getBySourceAndLocation(self, sourcepackagerelease, archive,
+                               distroarchseries):
+        """See IBinaryPackageBuildSet."""
+        # First we try to follow any binaries built from the given source
+        # in a distroarchseries with the given architecturetag and published
+        # in the given (distroarchseries, archive) location.
+        # (Querying all architectures and then picking the right one out
+        # of the result turns out to be much faster than querying for
+        # just the architecture we want).
+        builds_by_arch = self._findBySourceAndLocation(
+            sourcepackagerelease, archive, distroarchseries.distroseries)
+        build = builds_by_arch.get(distroarchseries.architecturetag)
+        if build is not None:
+            # If there was any published binary we can use its original build.
+            # This case covers the situations when both source and binaries
+            # got copied from another location.
+            return build
+
+        # If there was no published binary we have to try to find a
+        # suitable build in all possible location across the distroseries
+        # inheritance tree. See below.
+        clause_tables = ['DistroArchSeries']
+        queries = [
+            "DistroArchSeries.id = BinaryPackageBuild.distro_arch_series AND "
+            "BinaryPackageBuild.archive = %s AND "
+            "DistroArchSeries.architecturetag = %s AND "
+            "BinaryPackageBuild.source_package_release = %s" % (
+            sqlvalues(
+                archive.id, distroarchseries.architecturetag,
+                sourcepackagerelease))]
+
+        # Query only the last build record for this sourcerelease
+        # across all possible locations.
+        query = " AND ".join(queries)
+
+        return BinaryPackageBuild.selectFirst(
+            query, clauseTables=clause_tables,
+            orderBy=['-date_created'])
+
     def getStatusSummaryForBuilds(self, builds):
         """See `IBinaryPackageBuildSet`."""
         # Create a small helper function to collect the builds for a given
@@ -1343,7 +1429,8 @@
         Return the just-created `IBinaryPackageBuild` record already
         scored or None if a suitable build is already present.
         """
-        build_candidate = sourcepackagerelease.getBuildByArch(arch, archive)
+        build_candidate = self.getBySourceAndLocation(
+            sourcepackagerelease, archive, arch)
 
         # Check DistroArchSeries database IDs because the object belongs
         # to different transactions (architecture_available is cached).
@@ -1352,7 +1439,8 @@
              build_candidate.status == BuildStatus.FULLYBUILT)):
             return None
 
-        build = sourcepackagerelease.createBuild(
+        build = self.new(
+            source_package_release=sourcepackagerelease,
             distro_arch_series=arch, archive=archive, pocket=pocket)
         # Create the builds in suspended mode for disabled archives.
         build_queue = build.queueBuild(suspended=not archive.enabled)

=== modified file 'lib/lp/soyuz/model/packagecloner.py'
--- lib/lp/soyuz/model/packagecloner.py	2013-09-10 06:28:26 +0000
+++ lib/lp/soyuz/model/packagecloner.py	2014-10-31 08:42:03 +0000
@@ -16,7 +16,6 @@
 from zope.interface import implements
 from zope.security.proxy import removeSecurityProxy
 
-from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.database.constants import UTC_NOW
 from lp.services.database.interfaces import IStore
 from lp.services.database.sqlbase import (
@@ -58,8 +57,7 @@
     implements(IPackageCloner)
 
     def clonePackages(self, origin, destination, distroarchseries_list=None,
-                      processors=None, sourcepackagenames=None,
-                      always_create=False):
+                      processors=None, sourcepackagenames=None):
         """Copies packages from origin to destination package location.
 
         Binary packages are only copied for the `DistroArchSeries` pairs
@@ -78,9 +76,6 @@
         @param sourcepackagenames: the sourcepackages to copy to the
             destination
         @type sourcepackagenames: Iterable
-        @param always_create: if we should create builds for every source
-            package copied, useful if no binaries are to be copied.
-        @type always_create: Boolean
         """
         # First clone the source packages.
         self._clone_source_packages(
@@ -99,11 +94,10 @@
 
         self._create_missing_builds(
             destination.distroseries, destination.archive,
-            distroarchseries_list, processors, always_create)
+            distroarchseries_list, processors)
 
     def _create_missing_builds(self, distroseries, archive,
-                               distroarchseries_list, processors,
-                               always_create):
+                               distroarchseries_list, processors):
         """Create builds for all cloned source packages.
 
         :param distroseries: the distro series for which to create builds.
@@ -132,16 +126,7 @@
             distroseries=distroseries, status=active_publishing_status)
 
         for pubrec in sources_published:
-            builds = pubrec.createMissingBuilds(
-                architectures_available=architectures)
-            # If the last build was sucessful, we should create a new
-            # build, since createMissingBuilds() won't.
-            if not builds and always_create:
-                for arch in architectures:
-                    build = pubrec.sourcepackagerelease.createBuild(
-                        distro_arch_series=arch, archive=archive,
-                        pocket=PackagePublishingPocket.RELEASE)
-                    build.queueBuild(suspended=not archive.enabled)
+            pubrec.createMissingBuilds(architectures_available=architectures)
             # Commit to avoid MemoryError: bug 304459
             transaction.commit()
 
@@ -269,7 +254,7 @@
 
         self._create_missing_builds(
             destination.distroseries, destination.archive, (),
-            processors, False)
+            processors)
 
     def _compute_packageset_delta(self, origin):
         """Given a source/target archive find obsolete or missing packages.

=== modified file 'lib/lp/soyuz/model/sourcepackagerelease.py'
--- lib/lp/soyuz/model/sourcepackagerelease.py	2014-06-11 18:14:35 +0000
+++ lib/lp/soyuz/model/sourcepackagerelease.py	2014-10-31 08:42:03 +0000
@@ -26,7 +26,6 @@
     StringCol,
     )
 from storm.expr import Join
-from storm.info import ClassAlias
 from storm.locals import (
     Desc,
     Int,
@@ -297,112 +296,6 @@
         else:
             return 0.0
 
-    def createBuild(self, distro_arch_series, pocket, archive, processor=None,
-                    status=None):
-        """See ISourcePackageRelease."""
-        # If a processor is not provided, use the DAS' processor.
-        if processor is None:
-            processor = distro_arch_series.processor
-
-        if status is None:
-            status = BuildStatus.NEEDSBUILD
-
-        # Force the current timestamp instead of the default
-        # UTC_NOW for the transaction, avoid several row with
-        # same datecreated.
-        date_created = datetime.datetime.now(pytz.timezone('UTC'))
-
-        return getUtility(IBinaryPackageBuildSet).new(
-            distro_arch_series=distro_arch_series,
-            source_package_release=self,
-            processor=processor,
-            status=status,
-            date_created=date_created,
-            pocket=pocket,
-            archive=archive)
-
-    def findBuildsByArchitecture(self, distroseries, archive):
-        """Find associated builds, by architecture.
-
-        Looks for `BinaryPackageBuild` records for this source package
-        release, with publication records in the distroseries associated with
-        `distroarchseries`.  There should be at most one of these per
-        architecture.
-
-        :param distroarchseries: `DistroArchSeries` to look for.
-        :return: A dict mapping architecture tags (in string form,
-            e.g. 'i386') to `BinaryPackageBuild`s for that build.
-        """
-        # Avoid circular imports.
-        from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
-        from lp.soyuz.model.distroarchseries import DistroArchSeries
-        from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
-
-        BuildDAS = ClassAlias(DistroArchSeries, 'BuildDAS')
-        PublishDAS = ClassAlias(DistroArchSeries, 'PublishDAS')
-
-        query = Store.of(self).find(
-            (BuildDAS.architecturetag, BinaryPackageBuild),
-            BinaryPackageBuild.source_package_release == self,
-            BinaryPackageRelease.buildID == BinaryPackageBuild.id,
-            BuildDAS.id == BinaryPackageBuild.distro_arch_series_id,
-            BinaryPackagePublishingHistory.binarypackagereleaseID ==
-                BinaryPackageRelease.id,
-            BinaryPackagePublishingHistory.archiveID == archive.id,
-            PublishDAS.id ==
-                BinaryPackagePublishingHistory.distroarchseriesID,
-            PublishDAS.distroseriesID == distroseries.id,
-            # Architecture-independent binary package releases are built
-            # in the nominated arch-indep architecture but published in
-            # all architectures.  This condition makes sure we consider
-            # only builds that have been published in their own
-            # architecture.
-            PublishDAS.architecturetag == BuildDAS.architecturetag)
-        results = list(query.config(distinct=True))
-        mapped_results = dict(results)
-        assert len(mapped_results) == len(results), (
-            "Found multiple build candidates per architecture: %s.  "
-            "This may mean that we have a serious problem in our DB model.  "
-            "Further investigation is required."
-            % [(tag, build.id) for tag, build in results])
-        return mapped_results
-
-    def getBuildByArch(self, distroarchseries, archive):
-        """See ISourcePackageRelease."""
-        # First we try to follow any binaries built from the given source
-        # in a distroarchseries with the given architecturetag and published
-        # in the given (distroarchseries, archive) location.
-        # (Querying all architectures and then picking the right one out
-        # of the result turns out to be much faster than querying for
-        # just the architecture we want).
-        builds_by_arch = self.findBuildsByArchitecture(
-            distroarchseries.distroseries, archive)
-        build = builds_by_arch.get(distroarchseries.architecturetag)
-        if build is not None:
-            # If there was any published binary we can use its original build.
-            # This case covers the situations when both source and binaries
-            # got copied from another location.
-            return build
-
-        # If there was no published binary we have to try to find a
-        # suitable build in all possible location across the distroseries
-        # inheritance tree. See below.
-        clause_tables = ['DistroArchSeries']
-        queries = [
-            "DistroArchSeries.id = BinaryPackageBuild.distro_arch_series AND "
-            "BinaryPackageBuild.archive = %s AND "
-            "DistroArchSeries.architecturetag = %s AND "
-            "BinaryPackageBuild.source_package_release = %s" % (
-            sqlvalues(archive.id, distroarchseries.architecturetag, self))]
-
-        # Query only the last build record for this sourcerelease
-        # across all possible locations.
-        query = " AND ".join(queries)
-
-        return BinaryPackageBuild.selectFirst(
-            query, clauseTables=clause_tables,
-            orderBy=['-date_created'])
-
     def override(self, component=None, section=None, urgency=None):
         """See ISourcePackageRelease."""
         if component is not None:

=== modified file 'lib/lp/soyuz/scripts/gina/handlers.py'
--- lib/lp/soyuz/scripts/gina/handlers.py	2014-06-11 10:09:30 +0000
+++ lib/lp/soyuz/scripts/gina/handlers.py	2014-10-31 08:42:03 +0000
@@ -181,7 +181,7 @@
         self.distro = self._get_distro(distro_name)
         self.distroseries = self._get_distroseries(distroseries_name)
 
-        self.archinfo = {}
+        self.arch_map = {}
         self.imported_sources = []
         self.imported_bins = {}
 
@@ -192,7 +192,7 @@
 
         self.sppublisher = SourcePackagePublisher(
             self.distroseries, pocket, self.component_override)
-        # This is initialized in ensure_archinfo
+        # This is initialized in ensure_arch
         self.bppublishers = {}
 
     def commit(self):
@@ -203,25 +203,23 @@
         """Rollback changes to the database."""
         self.ztm.abort()
 
-    def ensure_archinfo(self, archtag):
+    def ensure_arch(self, archtag):
         """Append retrived distroarchseries info to a dict."""
-        if archtag in self.archinfo.keys():
+        if archtag in self.arch_map:
             return
 
         # Get distroarchseries and processor from the architecturetag.
-        dar = DistroArchSeries.selectOneBy(
+        das = DistroArchSeries.selectOneBy(
                 distroseriesID=self.distroseries.id,
                 architecturetag=archtag)
-        if not dar:
+        if not das:
             raise DataSetupError("Error finding distroarchseries for %s/%s"
                                  % (self.distroseries.name, archtag))
 
-        processor = dar.processor
-        info = {'distroarchseries': dar, 'processor': processor}
-        self.archinfo[archtag] = info
+        self.arch_map[archtag] = das
 
         self.bppublishers[archtag] = BinaryPackagePublisher(
-            dar, self.pocket, self.component_override)
+            das, self.pocket, self.component_override)
         self.imported_bins[archtag] = []
 
     #
@@ -282,9 +280,8 @@
         happen, for instance, if a binary package didn't change over
         releases, or if Gina runs multiple times over the same release
         """
-        distroarchinfo = self.archinfo[archtag]
-        binarypackagerelease = self.bphandler.checkBin(binarypackagedata,
-                                                       distroarchinfo)
+        binarypackagerelease = self.bphandler.checkBin(
+            binarypackagedata, self.arch_map[archtag])
         if not binarypackagerelease:
             log.debug('BPR not found in preimport: %r %r %r' %
                 (binarypackagedata.package, binarypackagedata.version,
@@ -297,13 +294,12 @@
 
     def import_binarypackage(self, archtag, binarypackagedata):
         """Handler the binarypackage import process"""
-        distroarchinfo = self.archinfo[archtag]
-
         # We know that preimport_binarycheck has run
-        assert not self.bphandler.checkBin(binarypackagedata, distroarchinfo)
+        assert not self.bphandler.checkBin(
+            binarypackagedata, self.arch_map[archtag])
 
         # Find the sourcepackagerelease that generated this binarypackage.
-        distroseries = distroarchinfo['distroarchseries'].distroseries
+        distroseries = self.arch_map[archtag].distroseries
         sourcepackage = self.locate_sourcepackage(binarypackagedata,
                                                   distroseries)
         if not sourcepackage:
@@ -317,7 +313,7 @@
                                  binarypackagedata.source_version))
 
         binarypackagerelease = self.bphandler.createBinaryPackage(
-            binarypackagedata, sourcepackage, distroarchinfo, archtag)
+            binarypackagedata, sourcepackage, self.arch_map[archtag], archtag)
         self.publish_binarypackage(binarypackagerelease, binarypackagedata,
                                    archtag)
 
@@ -733,7 +729,7 @@
         self.archive_root = archive_root
         self.pocket = pocket
 
-    def checkBin(self, binarypackagedata, distroarchinfo):
+    def checkBin(self, binarypackagedata, distroarchseries):
         """Returns a binarypackage -- if it exists."""
         try:
             binaryname = BinaryPackageName.byName(binarypackagedata.package)
@@ -747,7 +743,7 @@
 
         clauseTables = ["BinaryPackageRelease", "DistroSeries",
                         "BinaryPackageBuild", "DistroArchSeries"]
-        distroseries = distroarchinfo['distroarchseries'].distroseries
+        distroseries = distroarchseries.distroseries
 
         # When looking for binaries, we need to remember that they are
         # shared between distribution releases, so match on the
@@ -777,7 +773,7 @@
                      distroseries.distribution.name))
         return bpr
 
-    def createBinaryPackage(self, bin, srcpkg, distroarchinfo, archtag):
+    def createBinaryPackage(self, bin, srcpkg, distroarchseries, archtag):
         """Create a new binarypackage."""
         fdir, fname = os.path.split(bin.filename)
         to_upload = check_not_in_librarian(fname, bin.archive_root, fdir)
@@ -788,7 +784,7 @@
         architecturespecific = (bin.architecture != "all")
 
         bin_name = getUtility(IBinaryPackageNameSet).ensure(bin.package)
-        build = self.ensureBuild(bin, srcpkg, distroarchinfo, archtag)
+        build = self.ensureBuild(bin, srcpkg, distroarchseries, archtag)
 
         # Create the binarypackage entry on lp db.
         binpkg = BinaryPackageRelease(
@@ -828,9 +824,8 @@
         # Return the binarypackage object.
         return binpkg
 
-    def ensureBuild(self, binary, srcpkg, distroarchinfo, archtag):
+    def ensureBuild(self, binary, srcpkg, distroarchseries, archtag):
         """Ensure a build record."""
-        distroarchseries = distroarchinfo['distroarchseries']
         distribution = distroarchseries.distroseries.distribution
         clauseTables = [
             "BinaryPackageBuild",
@@ -872,14 +867,9 @@
                         "for package %s (%s)" %
                         (build.id, binary.package, binary.version))
         else:
-            processor = distroarchinfo['processor']
             build = getUtility(IBinaryPackageBuildSet).new(
-                        processor=processor,
-                        distro_arch_series=distroarchseries,
-                        status=BuildStatus.FULLYBUILT,
-                        source_package_release=srcpkg,
-                        pocket=self.pocket,
-                        archive=distroarchseries.main_archive)
+                srcpkg, distroarchseries.main_archive, distroarchseries,
+                self.pocket, status=BuildStatus.FULLYBUILT)
         return build
 
 

=== modified file 'lib/lp/soyuz/scripts/gina/runner.py'
--- lib/lp/soyuz/scripts/gina/runner.py	2013-05-22 11:57:26 +0000
+++ lib/lp/soyuz/scripts/gina/runner.py	2014-10-31 08:42:03 +0000
@@ -110,7 +110,7 @@
 
     for archtag in archs:
         try:
-            importer_handler.ensure_archinfo(archtag)
+            importer_handler.ensure_arch(archtag)
         except DataSetupError:
             log.exception("Database setup required for run on %s", archtag)
             sys.exit(1)

=== modified file 'lib/lp/soyuz/scripts/initialize_distroseries.py'
--- lib/lp/soyuz/scripts/initialize_distroseries.py	2014-07-24 03:37:02 +0000
+++ lib/lp/soyuz/scripts/initialize_distroseries.py	2014-10-31 08:42:03 +0000
@@ -541,7 +541,7 @@
                         distroarchseries_list = ()
                     getUtility(IPackageCloner).clonePackages(
                         origin, destination, distroarchseries_list,
-                        processors, spns, self.rebuild)
+                        processors, spns)
                 else:
                     # There is only one available pocket in an unreleased
                     # series.

=== modified file 'lib/lp/soyuz/scripts/tests/test_add_missing_builds.py'
--- lib/lp/soyuz/scripts/tests/test_add_missing_builds.py	2013-05-31 05:47:53 +0000
+++ lib/lp/soyuz/scripts/tests/test_add_missing_builds.py	2014-10-31 08:42:03 +0000
@@ -7,6 +7,8 @@
 import subprocess
 import sys
 
+from zope.component import getUtility
+
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.config import config
 from lp.services.database.sqlbase import (
@@ -18,6 +20,7 @@
     ArchivePurpose,
     PackagePublishingStatus,
     )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.scripts.add_missing_builds import AddMissingBuilds
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
 from lp.testing import TestCaseWithFactory
@@ -78,14 +81,19 @@
 
     def getBuilds(self):
         """Helper to return build records."""
-        any_build_i386 = self.any.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_i386, self.ppa)
-        any_build_hppa = self.any.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_hppa, self.ppa)
-        all_build_i386 = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_i386, self.ppa)
-        all_build_hppa = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_hppa, self.ppa)
+        bpbs = getUtility(IBinaryPackageBuildSet)
+        any_build_i386 = bpbs.getBySourceAndLocation(
+            self.any.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_i386)
+        any_build_hppa = bpbs.getBySourceAndLocation(
+            self.any.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_hppa)
+        all_build_i386 = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_i386)
+        all_build_hppa = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_hppa)
         return (
             any_build_i386, any_build_hppa, all_build_i386, all_build_hppa)
 
@@ -142,10 +150,13 @@
         # The arch-all package is architecture-independent, so it will
         # only get a build for i386 which is the nominated architecture-
         # independent build arch.
-        all_build_i386 = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_i386, self.ppa)
-        all_build_hppa = self.all.sourcepackagerelease.getBuildByArch(
-            self.stp.breezy_autotest_hppa, self.ppa)
+        bpbs = getUtility(IBinaryPackageBuildSet)
+        all_build_i386 = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_i386)
+        all_build_hppa = bpbs.getBySourceAndLocation(
+            self.all.sourcepackagerelease, self.ppa,
+            self.stp.breezy_autotest_hppa)
         self.assertIsNot(all_build_i386, None)
         self.assertIs(all_build_hppa, None)
 

=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2014-07-25 00:23:51 +0000
+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2014-10-31 08:42:03 +0000
@@ -22,6 +22,7 @@
     SourcePackageFormat,
     )
 from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.packageset import (
     IPackagesetSet,
@@ -596,11 +597,11 @@
         udev_src = udev_bin.build.source_package_release
         self.assertEqual(udev_src.title, u'udev - 0.1-1')
         # The build of udev 0.1-1 has been copied across.
-        child_udev = udev_src.getBuildByArch(
-            child[parent_das.architecturetag], child.main_archive)
-        parent_udev = udev_src.getBuildByArch(
-            parent[parent_das.architecturetag],
-            parent.main_archive)
+        bpbs = getUtility(IBinaryPackageBuildSet)
+        child_udev = bpbs.getBySourceAndLocation(
+            udev_src, child.main_archive, child[parent_das.architecturetag])
+        parent_udev = bpbs.getBySourceAndLocation(
+            udev_src, parent.main_archive, parent[parent_das.architecturetag])
         self.assertEqual(parent_udev.id, child_udev.id)
         # We also inherit the permitted source formats from our parent.
         self.assertTrue(

=== modified file 'lib/lp/soyuz/tests/test_binarypackagebuild.py'
--- lib/lp/soyuz/tests/test_binarypackagebuild.py	2014-07-24 09:37:03 +0000
+++ lib/lp/soyuz/tests/test_binarypackagebuild.py	2014-10-31 08:42:03 +0000
@@ -89,9 +89,9 @@
 
     def create_previous_build(self, duration):
         spr = self.build.source_package_release
-        build = spr.createBuild(
-            distro_arch_series=self.build.distro_arch_series,
-            archive=self.build.archive, pocket=self.build.pocket)
+        build = getUtility(IBinaryPackageBuildSet).new(
+            spr, self.build.archive, self.build.distro_arch_series,
+            self.build.pocket)
         now = datetime.now(pytz.UTC)
         build.updateStatus(
             BuildStatus.BUILDING,

=== modified file 'lib/lp/soyuz/tests/test_build.py'
--- lib/lp/soyuz/tests/test_build.py	2013-11-28 08:51:32 +0000
+++ lib/lp/soyuz/tests/test_build.py	2014-10-31 08:42:03 +0000
@@ -23,7 +23,10 @@
     PackagePublishingPriority,
     PackageUploadStatus,
     )
-from lp.soyuz.interfaces.binarypackagebuild import CannotBeRescored
+from lp.soyuz.interfaces.binarypackagebuild import (
+    CannotBeRescored,
+    IBinaryPackageBuildSet,
+    )
 from lp.soyuz.interfaces.component import IComponentSet
 from lp.soyuz.interfaces.publishing import PackagePublishingStatus
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
@@ -154,8 +157,9 @@
         # current_component returns None in that case.
         spph = self.publisher.getPubSource()
         other_das = self.factory.makeDistroArchSeries()
-        build = spph.sourcepackagerelease.createBuild(
-            other_das, PackagePublishingPocket.RELEASE, spph.archive)
+        build = getUtility(IBinaryPackageBuildSet).new(
+            spph.sourcepackagerelease, spph.archive, other_das,
+            PackagePublishingPocket.RELEASE)
         self.assertIs(None, build.current_component)
 
     def test_retry_for_released_series(self):

=== modified file 'lib/lp/soyuz/tests/test_build_set.py'
--- lib/lp/soyuz/tests/test_build_set.py	2014-10-31 03:12:58 +0000
+++ lib/lp/soyuz/tests/test_build_set.py	2014-10-31 08:42:03 +0000
@@ -9,13 +9,20 @@
 from lp.buildmaster.enums import BuildStatus
 from lp.registry.interfaces.person import IPersonSet
 from lp.registry.interfaces.pocket import PackagePublishingPocket
-from lp.soyuz.enums import ArchivePurpose
+from lp.soyuz.enums import (
+    ArchivePurpose,
+    SourcePackageFormat,
+    )
 from lp.soyuz.interfaces.archivearch import IArchiveArchSet
 from lp.soyuz.interfaces.binarypackagebuild import (
     BuildSetStatus,
     IBinaryPackageBuildSet,
     )
+from lp.soyuz.interfaces.sourcepackageformat import (
+    ISourcePackageFormatSelectionSet,
+    )
 from lp.soyuz.model.binarypackagebuild import BinaryPackageBuildSet
+from lp.soyuz.scripts.packagecopier import do_copy
 from lp.soyuz.tests.test_publishing import (
     SoyuzTestPublisher,
     TestNativePublishingBase,
@@ -24,7 +31,10 @@
     person_logged_in,
     TestCaseWithFactory,
     )
-from lp.testing.layers import LaunchpadFunctionalLayer
+from lp.testing.layers import (
+    LaunchpadFunctionalLayer,
+    ZopelessDatabaseLayer,
+    )
 from lp.testing.sampledata import ADMIN_EMAIL
 
 
@@ -306,3 +316,92 @@
         self.assertEqual(2, len(builds))
         self.assertEqual(self.avr_distroarch, builds[0].distro_arch_series)
         self.assertEqual(self.sparc_distroarch, builds[1].distro_arch_series)
+
+
+class TestFindBySourceAndLocation(TestCaseWithFactory):
+    """Tests for the _findBySourceAndLocation helper."""
+
+    layer = ZopelessDatabaseLayer
+
+    def test_finds_build_with_matching_pub(self):
+        # _findBySourceAndLocation finds builds for a source package
+        # release.  In particular, an arch-independent BPR is published in
+        # multiple architectures.  But findBuildsByArchitecture only counts
+        # the publication for the same architecture it was built in.
+        distroseries = self.factory.makeDistroSeries()
+        archive = distroseries.main_archive
+        # The series has a nominated arch-indep architecture.
+        distroseries.nominatedarchindep = self.factory.makeDistroArchSeries(
+            distroseries=distroseries)
+
+        bpb = self.factory.makeBinaryPackageBuild(
+            distroarchseries=distroseries.nominatedarchindep)
+        bpr = self.factory.makeBinaryPackageRelease(
+            build=bpb, architecturespecific=False)
+        spr = bpr.build.source_package_release
+
+        # The series also has other architectures.
+        self.factory.makeDistroArchSeries(distroseries=distroseries)
+
+        # makeBinaryPackagePublishingHistory will actually publish an
+        # arch-indep BPR everywhere.
+        self.factory.makeBinaryPackagePublishingHistory(
+            binarypackagerelease=bpr, archive=archive,
+            distroarchseries=distroseries.nominatedarchindep)
+
+        naked_spr = removeSecurityProxy(spr)
+        self.assertEqual(
+            {distroseries.nominatedarchindep.architecturetag: bpr.build},
+            BinaryPackageBuildSet()._findBySourceAndLocation(
+                naked_spr, archive, distroseries))
+
+
+class TestGetBySourceAndLocation(TestCaseWithFactory):
+    """Tests for BinaryPackageBuildSet.getBySourceAndLocation()."""
+
+    layer = ZopelessDatabaseLayer
+
+    def test_can_find_build_in_derived_distro_parent(self):
+        # If a derived distribution inherited its binaries from its
+        # parent then getBySourceAndLocation() should look in the parent
+        # to find the build.
+        dsp = self.factory.makeDistroSeriesParent()
+        parent_archive = dsp.parent_series.main_archive
+
+        # Create a built, published package in the parent archive.
+        spr = self.factory.makeSourcePackageRelease(
+            architecturehintlist='any')
+        parent_source_pub = self.factory.makeSourcePackagePublishingHistory(
+            sourcepackagerelease=spr, archive=parent_archive,
+            distroseries=dsp.parent_series)
+        das = self.factory.makeDistroArchSeries(
+            distroseries=dsp.parent_series, supports_virtualized=True)
+        orig_build = getUtility(IBinaryPackageBuildSet).new(
+            spr, parent_archive, das, PackagePublishingPocket.RELEASE,
+            status=BuildStatus.FULLYBUILT)
+        bpr = self.factory.makeBinaryPackageRelease(build=orig_build)
+        self.factory.makeBinaryPackagePublishingHistory(
+            binarypackagerelease=bpr, distroarchseries=das,
+            archive=parent_archive)
+
+        # Make an architecture in the derived series with the same
+        # archtag as the parent.
+        das_derived = self.factory.makeDistroArchSeries(
+            dsp.derived_series, architecturetag=das.architecturetag,
+            processor=das.processor, supports_virtualized=True)
+        # Now copy the package to the derived series, with binary.
+        derived_archive = dsp.derived_series.main_archive
+        getUtility(ISourcePackageFormatSelectionSet).add(
+            dsp.derived_series, SourcePackageFormat.FORMAT_1_0)
+
+        do_copy(
+            [parent_source_pub], derived_archive, dsp.derived_series,
+            PackagePublishingPocket.RELEASE, include_binaries=True,
+            check_permissions=False)
+
+        # Searching for the build in the derived series architecture
+        # should automatically pick it up from the parent.
+        found_build = getUtility(
+            IBinaryPackageBuildSet).getBySourceAndLocation(
+                spr, derived_archive, das_derived)
+        self.assertEqual(orig_build, found_build)

=== modified file 'lib/lp/soyuz/tests/test_sourcepackagerelease.py'
--- lib/lp/soyuz/tests/test_sourcepackagerelease.py	2013-10-10 18:37:49 +0000
+++ lib/lp/soyuz/tests/test_sourcepackagerelease.py	2014-10-31 08:42:03 +0000
@@ -20,13 +20,9 @@
 from lp.soyuz.enums import (
     ArchivePurpose,
     PackagePublishingStatus,
-    SourcePackageFormat,
     )
+from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.publishing import active_publishing_status
-from lp.soyuz.interfaces.sourcepackageformat import (
-    ISourcePackageFormatSelectionSet,
-    )
-from lp.soyuz.scripts.packagecopier import do_copy
 from lp.testing import (
     TestCaseWithFactory,
     )
@@ -208,89 +204,3 @@
             [by_status[status] for status in active_publishing_status],
             spr.getActiveArchSpecificPublications(
                 bpphs[0].archive, bpphs[0].distroseries, bpphs[0].pocket))
-
-
-class TestSourcePackageReleaseGetBuildByArch(TestCaseWithFactory):
-    """Tests for SourcePackageRelease.getBuildByArch()."""
-
-    layer = ZopelessDatabaseLayer
-
-    def test_can_find_build_in_derived_distro_parent(self):
-        # If a derived distribution inherited its binaries from its
-        # parent then getBuildByArch() should look in the parent to find
-        # the build.
-        dsp = self.factory.makeDistroSeriesParent()
-        parent_archive = dsp.parent_series.main_archive
-
-        # Create a built, published package in the parent archive.
-        spr = self.factory.makeSourcePackageRelease(
-            architecturehintlist='any')
-        parent_source_pub = self.factory.makeSourcePackagePublishingHistory(
-            sourcepackagerelease=spr, archive=parent_archive,
-            distroseries=dsp.parent_series)
-        das = self.factory.makeDistroArchSeries(
-            distroseries=dsp.parent_series, supports_virtualized=True)
-        orig_build = spr.createBuild(
-            das, PackagePublishingPocket.RELEASE, parent_archive,
-            status=BuildStatus.FULLYBUILT)
-        bpr = self.factory.makeBinaryPackageRelease(build=orig_build)
-        self.factory.makeBinaryPackagePublishingHistory(
-            binarypackagerelease=bpr, distroarchseries=das,
-            archive=parent_archive)
-
-        # Make an architecture in the derived series with the same
-        # archtag as the parent.
-        das_derived = self.factory.makeDistroArchSeries(
-            dsp.derived_series, architecturetag=das.architecturetag,
-            processor=das.processor, supports_virtualized=True)
-        # Now copy the package to the derived series, with binary.
-        derived_archive = dsp.derived_series.main_archive
-        getUtility(ISourcePackageFormatSelectionSet).add(
-            dsp.derived_series, SourcePackageFormat.FORMAT_1_0)
-
-        do_copy(
-            [parent_source_pub], derived_archive, dsp.derived_series,
-            PackagePublishingPocket.RELEASE, include_binaries=True,
-            check_permissions=False)
-
-        # Searching for the build in the derived series architecture
-        # should automatically pick it up from the parent.
-        found_build = spr.getBuildByArch(das_derived, derived_archive)
-        self.assertEqual(orig_build, found_build)
-
-
-class TestFindBuildsByArchitecture(TestCaseWithFactory):
-    """Tests for SourcePackageRelease.findBuildsByArchitecture."""
-
-    layer = ZopelessDatabaseLayer
-
-    def test_finds_build_with_matching_pub(self):
-        # findBuildsByArchitecture finds builds for a source package
-        # release.  In particular, an arch-independent BPR is published in
-        # multiple architectures.  But findBuildsByArchitecture only counts
-        # the publication for the same architecture it was built in.
-        distroseries = self.factory.makeDistroSeries()
-        archive = distroseries.main_archive
-        # The series has a nominated arch-indep architecture.
-        distroseries.nominatedarchindep = self.factory.makeDistroArchSeries(
-            distroseries=distroseries)
-
-        bpb = self.factory.makeBinaryPackageBuild(
-            distroarchseries=distroseries.nominatedarchindep)
-        bpr = self.factory.makeBinaryPackageRelease(
-            build=bpb, architecturespecific=False)
-        spr = bpr.build.source_package_release
-
-        # The series also has other architectures.
-        self.factory.makeDistroArchSeries(distroseries=distroseries)
-
-        # makeBinaryPackagePublishingHistory will actually publish an
-        # arch-indep BPR everywhere.
-        self.factory.makeBinaryPackagePublishingHistory(
-            binarypackagerelease=bpr, archive=archive,
-            distroarchseries=distroseries.nominatedarchindep)
-
-        naked_spr = removeSecurityProxy(spr)
-        self.assertEqual(
-            {distroseries.nominatedarchindep.architecturetag: bpr.build},
-            naked_spr.findBuildsByArchitecture(distroseries, archive))

=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py	2014-09-01 03:41:31 +0000
+++ lib/lp/testing/factory.py	2014-10-31 08:42:03 +0000
@@ -75,7 +75,6 @@
 from lp.blueprints.enums import (
     NewSpecificationDefinitionStatus,
     SpecificationDefinitionStatus,
-    SpecificationPriority,
     SpecificationWorkItemStatus,
     )
 from lp.blueprints.interfaces.specification import ISpecificationSet
@@ -3578,9 +3577,9 @@
         :param builder: An optional builder to assign.
         :param status: The BuildStatus for the build.
         """
-        if processor is None:
-            processor = self.makeProcessor()
         if distroarchseries is None:
+            if processor is None:
+                processor = self.makeProcessor()
             if source_package_release is not None:
                 distroseries = source_package_release.upload_distroseries
             elif archive is not None:
@@ -3590,6 +3589,11 @@
                 distroseries = self.makeDistroSeries()
             distroarchseries = self.makeDistroArchSeries(
                 distroseries=distroseries, processor=processor)
+        else:
+            if (processor is not None
+                    and processor != distroarchseries.processor):
+                raise AssertionError(
+                    "DistroArchSeries and Processor must match.")
         if archive is None:
             if source_package_release is None:
                 archive = distroarchseries.main_archive
@@ -3612,18 +3616,14 @@
                 pocket=pocket)
         if status is None:
             status = BuildStatus.NEEDSBUILD
-        if date_created is None:
-            date_created = self.getUniqueDate()
         admins = getUtility(ILaunchpadCelebrities).admin
         with person_logged_in(admins.teamowner):
             binary_package_build = getUtility(IBinaryPackageBuildSet).new(
                 source_package_release=source_package_release,
-                processor=processor,
                 distro_arch_series=distroarchseries,
                 status=status,
                 archive=archive,
                 pocket=pocket,
-                date_created=date_created,
                 builder=builder)
         IStore(binary_package_build).flush()
         return binary_package_build