← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/generalise-add-missing-builds into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/generalise-add-missing-builds into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  #726900 ppa-add-missing-builds.py should work for more than just PPAs
  https://bugs.launchpad.net/bugs/726900
  #726904 ppa-add-missing-builds.py should parse P-a-s
  https://bugs.launchpad.net/bugs/726904

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/generalise-add-missing-builds/+merge/51873

This branch renames ppa-add-missing-builds.py to add-missing-builds.py, and makes it work for the primary archive too.

Rather than duplicating the archive selection logic, I turned AddMissingBuilds into a SoyuzScript. This allowed deletion of much of its code, as I reused the suite selection too.

The other change is the introduction of Packages-arch-specific support. This should be reasonably clear. determineArchitecturesToBuild knows not to respect P-a-s for PPA builds, so it is fine to give it to createMissingBuilds unconditionally.

I added a test to verify that it works for primary archives with P-a-s. The script's parsing of P-a-s from the right place is difficult to check in the test suite, but I've confirmed that it works.
-- 
https://code.launchpad.net/~wgrant/launchpad/generalise-add-missing-builds/+merge/51873
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/generalise-add-missing-builds into lp:launchpad.
=== renamed file 'lib/lp/soyuz/scripts/ppa_add_missing_builds.py' => 'lib/lp/soyuz/scripts/add_missing_builds.py'
--- lib/lp/soyuz/scripts/ppa_add_missing_builds.py	2011-01-12 15:25:24 +0000
+++ lib/lp/soyuz/scripts/add_missing_builds.py	2011-03-02 10:22:43 +0000
@@ -4,23 +4,29 @@
 
 import sys
 
-from zope.component import getUtility
-
+from canonical.config import config
 from lp.app.errors import NotFoundError
-from lp.services.scripts.base import LaunchpadScript
+from lp.services.scripts.base import LaunchpadScriptFailure
+from lp.soyuz.pas import BuildDaemonPackagesArchSpecific
+from lp.soyuz.scripts.ftpmasterbase import (
+    SoyuzScript,
+    SoyuzScriptError,
+    )
 from lp.soyuz.enums import PackagePublishingStatus
 
 
-class PPAMissingBuilds(LaunchpadScript):
+class AddMissingBuilds(SoyuzScript):
     """Helper class to create builds in PPAs for requested architectures."""
 
-    def add_missing_ppa_builds(self, ppa, required_arches, distroseries):
-        """For a PPA, create builds as necessary.
+    def add_missing_builds(self, archive, required_arches, pas_verify,
+                           distroseries, pocket):
+        """Create builds in an archive as necessary.
 
-        :param ppa: The PPA
-        :param required_arches: A list of `DistroArchSeries`
+        :param archive: The `Archive`.
+        :param required_arches: A list of `DistroArchSeries`.
         :param distroseries: The context `DistroSeries` in which to create
             builds.
+        :param pocket: The context `PackagePublishingPocket`.
         """
         # Listify the architectures to avoid hitting this MultipleJoin
         # multiple times.
@@ -50,8 +56,9 @@
             self.logger.error("Requested architectures not available")
             return
 
-        sources = ppa.getPublishedSources(
+        sources = archive.getPublishedSources(
             distroseries=distroseries,
+            pocket=pocket,
             status=PackagePublishingStatus.PUBLISHED)
         if not bool(sources):
             self.logger.info("No sources published, nothing to do.")
@@ -63,68 +70,46 @@
         for pubrec in sources:
             self.logger.info("Considering %s" % pubrec.displayname)
             builds = pubrec.createMissingBuilds(
-                architectures_available=doable_arch_set, logger=self.logger)
+                architectures_available=doable_arch_set,
+                pas_verify=pas_verify, logger=self.logger)
             if len(builds) > 0:
                 self.logger.info("Created %s build(s)" % len(builds))
 
     def add_my_options(self):
         """Command line options for this script."""
+        self.add_archive_options()
+        self.add_distro_options()
         self.parser.add_option(
             "-a", action="append", dest='arch_tags', default=[])
-        self.parser.add_option("-s", action="store", dest='distroseries_name')
-        self.parser.add_option(
-            "-d", action="store", dest='distribution_name', default="ubuntu")
-        self.parser.add_option(
-            "--owner", action="store", dest='ppa_owner_name')
-        self.parser.add_option(
-            "--ppa", action="store", dest='ppa_name', default="ppa")
 
     def main(self):
         """Entry point for `LaunchpadScript`s."""
+        try:
+            self.setupLocation()
+        except SoyuzScriptError, err:
+            raise LaunchpadScriptFailure(err)
+
         if not self.options.arch_tags:
             self.parser.error("Specify at least one architecture.")
 
-        if not self.options.distroseries_name:
-            self.parser.error("Specify a distroseries.")
-
-        if not self.options.ppa_owner_name:
-            self.parser.error("Specify a PPA owner name.")
-
-        # Avoid circular imports by importing here.
-        from lp.registry.interfaces.distribution import IDistributionSet
-        distro = getUtility(IDistributionSet).getByName(
-            self.options.distribution_name)
-        if distro is None:
-            self.parser.error("%s not found" % self.options.distribution_name)
-
-        try:
-            distroseries = distro.getSeries(self.options.distroseries_name)
-        except NotFoundError:
-            self.parser.error("%s not found" % self.options.distroseries_name)
-
         arches = []
         for arch_tag in self.options.arch_tags:
             try:
-                das = distroseries.getDistroArchSeries(arch_tag)
+                das = self.location.distroseries.getDistroArchSeries(arch_tag)
                 arches.append(das)
             except NotFoundError:
                 self.parser.error(
                     "%s not a valid architecture for %s" % (
-                        arch_tag, self.options.distroseries_name))
-
-        from lp.registry.interfaces.person import IPersonSet
-        owner = getUtility(IPersonSet).getByName(self.options.ppa_owner_name)
-        if owner is None:
-            self.parser.error("%s not found" % self.options.ppa_owner_name)
-
-        try:
-            ppa = owner.getPPAByName(self.options.ppa_name)
-        except NotFoundError:
-            self.parser.error("%s not found" % self.options.ppa_name)
+                        arch_tag, self.location.distroseries.name))
+
+        pas_verify = BuildDaemonPackagesArchSpecific(
+            config.builddmaster.root, self.location.distroseries)
 
         # I'm tired of parsing options.  Let's do it.
         try:
-            self.add_missing_ppa_builds(ppa, arches, distroseries)
+            self.add_missing_builds(
+                self.location.archive, arches, pas_verify,
+                self.location.distroseries, self.location.pocket)
             self.txn.commit()
             self.logger.info("Finished adding builds.")
         except Exception, err:
@@ -133,4 +118,3 @@
             self.logger.info("Errors, aborted transaction.")
             sys.exit(1)
 
-

=== renamed file 'lib/lp/soyuz/scripts/tests/test_ppa_add_missing_builds.py' => 'lib/lp/soyuz/scripts/tests/test_add_missing_builds.py'
--- lib/lp/soyuz/scripts/tests/test_ppa_add_missing_builds.py	2010-12-20 03:21:03 +0000
+++ lib/lp/soyuz/scripts/tests/test_add_missing_builds.py	2011-03-02 10:22:43 +0000
@@ -1,11 +1,13 @@
 # Copyright 2010 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
-"""Test the ppa-add-missing-builds.py script. """
+"""Test the add-missing-builds.py script. """
 
 import os
 import subprocess
 import sys
+import shutil
+import tempfile
 
 from canonical.config import config
 from canonical.database.sqlbase import (
@@ -13,18 +15,20 @@
     flush_database_updates,
     )
 from canonical.testing.layers import LaunchpadZopelessLayer
+from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.services.log.logger import BufferLogger
 from lp.soyuz.enums import (
     ArchivePurpose,
     PackagePublishingStatus,
     )
-from lp.soyuz.scripts.ppa_add_missing_builds import PPAMissingBuilds
+from lp.soyuz.pas import BuildDaemonPackagesArchSpecific
+from lp.soyuz.scripts.add_missing_builds import AddMissingBuilds
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
 from lp.testing import TestCaseWithFactory
 
 
-class TestPPAAddMissingBuilds(TestCaseWithFactory):
-    """Test the ppa-add-missing-builds.py script. """
+class TestAddMissingBuilds(TestCaseWithFactory):
+    """Test the add-missing-builds.py script. """
 
     layer = LaunchpadZopelessLayer
     dbuser = config.builddmaster.dbuser
@@ -40,7 +44,8 @@
         self.stp.breezy_autotest_hppa.supports_virtualized = True
 
         # Create an arch-any and an arch-all source in a PPA.
-        self.ppa = self.factory.makeArchive(purpose=ArchivePurpose.PPA)
+        self.ppa = self.factory.makeArchive(
+            purpose=ArchivePurpose.PPA, distribution=self.stp.ubuntutest)
         self.all = self.stp.getPubSource(
             sourcename="all", architecturehintlist="all", archive=self.ppa,
             status=PackagePublishingStatus.PUBLISHED)
@@ -60,7 +65,7 @@
         if test_args is None:
             test_args = []
         script = os.path.join(
-            config.root, "scripts", "ppa-add-missing-builds.py")
+            config.root, "scripts", "add-missing-builds.py")
         args = [sys.executable, script]
         args.extend(test_args)
         process = subprocess.Popen(
@@ -70,10 +75,21 @@
 
     def getScript(self):
         """Return an instance of the script object."""
-        script = PPAMissingBuilds("test", test_args=[])
+        script = AddMissingBuilds("test", test_args=[])
         script.logger = BufferLogger()
         return script
 
+    def makePasVerifier(self, content, series):
+        """Create a BuildDaemonPackagesArchSpecific."""
+        temp_dir = tempfile.mkdtemp()
+        filename = os.path.join(temp_dir, "Packages-arch-specific")
+        file = open(filename, "w")
+        file.write(content)
+        file.close()
+        verifier = BuildDaemonPackagesArchSpecific(temp_dir, series)
+        shutil.rmtree(temp_dir)
+        return verifier
+
     def getBuilds(self):
         """Helper to return build records."""
         any_build_i386 = self.any.sourcepackagerelease.getBuildByArch(
@@ -121,8 +137,8 @@
             "-s", "breezy-autotest",
             "-a", "i386",
             "-a", "hppa",
-            "--owner", "%s" % self.ppa.owner.name,
-            "--ppa", self.ppa.name,
+            "--ppa", "%s" % self.ppa.owner.name,
+            "--ppa-name", self.ppa.name,
             ]
         code, stdout, stderr = self.runScript(args)
         self.assertEqual(
@@ -153,6 +169,31 @@
         self.any.requestDeletion(self.ppa.owner)
 
         script = self.getScript()
-        script.add_missing_ppa_builds(
-            self.ppa, self.required_arches, self.stp.breezy_autotest)
+        script.add_missing_builds(
+            self.ppa, self.required_arches, None, self.stp.breezy_autotest,
+            PackagePublishingPocket.RELEASE)
         self.assertNoBuilds()
+
+    def testPrimaryArchiveWithPas(self):
+        """Test that the script functions correctly on a primary archive.
+
+        Also verifies that it respects Packages-arch-specific in this case.
+        """
+        archive = self.stp.ubuntutest.main_archive
+        any = self.stp.getPubSource(
+            sourcename="any", architecturehintlist="any",
+            status=PackagePublishingStatus.PUBLISHED)
+        pas_any = self.stp.getPubSource(
+            sourcename="pas-any", architecturehintlist="any",
+            status=PackagePublishingStatus.PUBLISHED)
+
+        verifier = self.makePasVerifier(
+            "%pas-any: hppa", self.stp.breezy_autotest)
+        script = self.getScript()
+        script.add_missing_builds(
+            archive, self.required_arches, verifier,
+            self.stp.breezy_autotest, PackagePublishingPocket.RELEASE)
+
+        # any gets i386 and hppa builds, but pas-any is restricted to hppa.
+        self.assertEquals(len(any.getBuilds()), 2)
+        self.assertEquals(len(pas_any.getBuilds()), 1)

=== renamed file 'scripts/ppa-add-missing-builds.py' => 'scripts/add-missing-builds.py'
--- scripts/ppa-add-missing-builds.py	2011-01-13 17:39:55 +0000
+++ scripts/add-missing-builds.py	2011-03-02 10:22:43 +0000
@@ -7,10 +7,10 @@
 
 import _pythonpath
 
-from lp.soyuz.scripts.ppa_add_missing_builds import PPAMissingBuilds
+from lp.soyuz.scripts.add_missing_builds import AddMissingBuilds
 from canonical.config import config
 
 if __name__ == "__main__":
-    script = PPAMissingBuilds(
-        "ppa-add-missing-builds", dbuser=config.uploader.dbuser)
+    script = AddMissingBuilds(
+        "add-missing-builds", dbuser=config.uploader.dbuser)
     script.lock_and_run()