launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #28258
[Merge] ~cjwatson/launchpad:move-publishing-queries into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:move-publishing-queries into launchpad:master.
Commit message:
Move publishing queries from DistroSeries to PublishingSet
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/417751
The existence of `DistroSeries.getSourcePackagePublishing` and `DistroSeries.getBinaryPackagePublishing` was a historical anomaly, as this sort of publishing-specific code should live in `lp.soyuz` or `lp.archivepublisher`. Move these to the more appropriate `PublishingSet.getSourcesForPublishing` and `PublishingSet.getBinariesForPublishing`.
As well as cleaning up some minor technical debt, this helps to prepare for Artifactory publishing, where we're likely to need to be able to query for publications in an archive without filtering by series.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:move-publishing-queries into launchpad:master.
diff --git a/lib/lp/archivepublisher/publishing.py b/lib/lp/archivepublisher/publishing.py
index a5a0cc4..e280b79 100644
--- a/lib/lp/archivepublisher/publishing.py
+++ b/lib/lp/archivepublisher/publishing.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2021 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__all__ = [
@@ -910,8 +910,9 @@ class Publisher:
get_sources_path(self._config, suite_name, component),
self._config.temproot, distroseries.index_compressors)
- for spp in distroseries.getSourcePackagePublishing(
- pocket, component, self.archive):
+ for spp in getUtility(IPublishingSet).getSourcesForPublishing(
+ archive=self.archive, distroseries=distroseries, pocket=pocket,
+ component=component):
stanza = build_source_stanza_fields(
spp.sourcepackagerelease, spp.component, spp.section)
source_index.write(stanza.makeOutput().encode('utf-8') + b'\n\n')
@@ -937,8 +938,9 @@ class Publisher:
self._config, suite_name, component, arch, subcomp),
self._config.temproot, distroseries.index_compressors)
- for bpp in distroseries.getBinaryPackagePublishing(
- arch.architecturetag, pocket, component, self.archive):
+ for bpp in getUtility(IPublishingSet).getBinariesForPublishing(
+ archive=self.archive, distroarchseries=arch, pocket=pocket,
+ component=component):
subcomp = FORMAT_TO_SUBCOMPONENT.get(
bpp.binarypackagerelease.binpackageformat)
if subcomp not in indices:
diff --git a/lib/lp/registry/doc/distroseries.txt b/lib/lp/registry/doc/distroseries.txt
index 7d202f5..82a8ff8 100644
--- a/lib/lp/registry/doc/distroseries.txt
+++ b/lib/lp/registry/doc/distroseries.txt
@@ -232,7 +232,6 @@ other things) the uploader for validating incoming uploads.
devel
translations
- >>> from lp.soyuz.interfaces.component import IComponentSet
>>> from lp.soyuz.interfaces.section import ISectionSet
>>> python = getUtility(ISectionSet).ensure('python')
@@ -490,50 +489,9 @@ upstream.
SourcePackagePublishingHistory
------------------------------
-IDistroSeries.getSourcePackagePublishing returns all the ISPPH
-records for a given status in a given pocket. It makes easy to
-generate a list of currently published sources for override-check, for
-instance. it can also be used to generate the archive packages list in
-the future.
-
- >>> ubuntu = getUtility(IDistributionSet)['ubuntu']
- >>> hoary = ubuntu['hoary']
- >>> component_main = getUtility(IComponentSet)['main']
- >>> component_multiverse = getUtility(IComponentSet)['multiverse']
- >>> debian_archive = getUtility(IDistributionSet)['debian'].main_archive
-
- >>> spphs = hoary.getSourcePackagePublishing(
- ... PackagePublishingPocket.RELEASE, component_main,
- ... warty.main_archive)
- >>> spphs.count()
- 6
- >>> for name in sorted(set(
- ... pkgpub.sourcepackagerelease.sourcepackagename.name
- ... for pkgpub in spphs)):
- ... print(name)
- alsa-utils
- evolution
- libstdc++
- linux-source-2.6.15
- netapplet
- pmount
- >>> hoary.getSourcePackagePublishing(
- ... PackagePublishingPocket.RELEASE, component_multiverse,
- ... hoary.main_archive).count()
- 0
- >>> hoary.getSourcePackagePublishing(
- ... PackagePublishingPocket.BACKPORTS, component_main,
- ... hoary.main_archive).count()
- 0
- >>> hoary.getSourcePackagePublishing(
- ... PackagePublishingPocket.RELEASE, component_main,
- ... debian_archive).count()
- 0
-
ISPP.getPublishedBinaries returns all the binaries generated by the
publication in question:
- >>> warty = ubuntu['warty']
>>> warty_pub_source = warty.main_archive.getPublishedSources(
... distroseries=warty, name=u'mozilla-firefox',
... status=PackagePublishingStatus.PUBLISHED).one()
@@ -566,36 +524,6 @@ publication in question:
>>> print(warty_mozilla_pub_bin.section.name)
base
-DistroSeries.getBinaryPackagePublishing will return
-BinaryPackagePublishingHistory objects for the DistroSeries:
-
- >>> warty = ubuntu['warty']
- >>> bpphs = warty.getBinaryPackagePublishing(
- ... "i386", PackagePublishingPocket.RELEASE, component_main,
- ... warty.main_archive)
- >>> bpphs.count()
- 8
- >>> 'mozilla-firefox' in set(
- ... pkgpub.binarypackagerelease.binarypackagename.name
- ... for pkgpub in bpphs)
- True
- >>> warty.getBinaryPackagePublishing(
- ... "nope", PackagePublishingPocket.RELEASE, component_main,
- ... warty.main_archive).count()
- 0
- >>> warty.getBinaryPackagePublishing(
- ... "i386", PackagePublishingPocket.RELEASE, component_multiverse,
- ... warty.main_archive).count()
- 0
- >>> warty.getBinaryPackagePublishing(
- ... "i386", PackagePublishingPocket.BACKPORTS, component_main,
- ... warty.main_archive).count()
- 0
- >>> warty.getBinaryPackagePublishing(
- ... "i386", PackagePublishingPocket.RELEASE, component_main,
- ... debian_archive).count()
- 0
-
getAllPublishedSources will return all publications with status PUBLISHED
and in the main archives for this distroseries:
diff --git a/lib/lp/registry/interfaces/distroseries.py b/lib/lp/registry/interfaces/distroseries.py
index d8c6370..ac2959c 100644
--- a/lib/lp/registry/interfaces/distroseries.py
+++ b/lib/lp/registry/interfaces/distroseries.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2021 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Interfaces including and related to IDistroSeries."""
@@ -729,26 +729,6 @@ class IDistroSeriesPublic(
def addSection(section):
"""SQLObject provided method to fill a related join key section."""
- def getBinaryPackagePublishing(archtag, pocket, component, archive):
- """Get BinaryPackagePublishings in a DistroSeries.
-
- Can optionally restrict the results by architecturetag, pocket and/or
- component.
-
- If archive is passed, restricted the results to the given archive,
- if it is suppressed the results will be restricted to the
- distribution 'main_archive'.
- """
-
- def getSourcePackagePublishing(pocket, component, archive):
- """Return a selectResult of ISourcePackagePublishingHistory.
-
- According status and pocket.
- If archive is passed, restricted the results to the given archive,
- if it is suppressed the results will be restricted to the
- distribution 'main_archive'.
- """
-
def searchPackages(text):
"""Search through the package cache for this distroseries and return
DistroSeriesBinaryPackage objects that match the given text.
diff --git a/lib/lp/registry/model/distroseries.py b/lib/lp/registry/model/distroseries.py
index cc209a5..8c3d76c 100644
--- a/lib/lp/registry/model/distroseries.py
+++ b/lib/lp/registry/model/distroseries.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2021 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Database classes for a distribution series."""
@@ -12,10 +12,7 @@ __all__ = [
import collections
from io import BytesIO
-from operator import (
- attrgetter,
- itemgetter,
- )
+from operator import itemgetter
import apt_pkg
from lazr.delegates import delegate_to
@@ -86,10 +83,6 @@ from lp.registry.model.person import Person
from lp.registry.model.series import SeriesMixin
from lp.registry.model.sourcepackage import SourcePackage
from lp.registry.model.sourcepackagename import SourcePackageName
-from lp.services.database.bulk import (
- load_referencing,
- load_related,
- )
from lp.services.database.constants import (
DEFAULT,
UTC_NOW,
@@ -116,10 +109,7 @@ from lp.services.database.stormexpr import (
IsTrue,
)
from lp.services.librarian.interfaces import ILibraryFileAliasSet
-from lp.services.librarian.model import (
- LibraryFileAlias,
- LibraryFileContent,
- )
+from lp.services.librarian.model import LibraryFileAlias
from lp.services.mail.signedmessage import signed_message_from_bytes
from lp.services.propertycache import (
cachedproperty,
@@ -146,9 +136,7 @@ from lp.soyuz.interfaces.queue import (
from lp.soyuz.interfaces.sourcepackageformat import (
ISourcePackageFormatSelectionSet,
)
-from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
from lp.soyuz.model.binarypackagename import BinaryPackageName
-from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
from lp.soyuz.model.component import Component
from lp.soyuz.model.distributionsourcepackagerelease import (
DistributionSourcePackageRelease,
@@ -159,10 +147,6 @@ from lp.soyuz.model.distroarchseries import (
)
from lp.soyuz.model.distroseriesbinarypackage import DistroSeriesBinaryPackage
from lp.soyuz.model.distroseriespackagecache import DistroSeriesPackageCache
-from lp.soyuz.model.files import (
- BinaryPackageFile,
- SourcePackageReleaseFile,
- )
from lp.soyuz.model.publishing import (
BinaryPackagePublishingHistory,
get_current_source_releases,
@@ -173,7 +157,6 @@ from lp.soyuz.model.queue import (
PackageUploadQueue,
PackageUploadSource,
)
-from lp.soyuz.model.section import Section
from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
from lp.translations.enums import LanguagePackType
from lp.translations.model.distroserieslanguage import (
@@ -1067,80 +1050,6 @@ class DistroSeries(SQLBase, BugTargetBase, HasSpecificationsMixin,
"""See `IDistroSeries`."""
return self._getAllBinaries().find(scheduleddeletiondate=None)
- def getSourcePackagePublishing(self, pocket, component, archive):
- """See `IDistroSeries`."""
- spphs = Store.of(self).find(
- SourcePackagePublishingHistory,
- SourcePackagePublishingHistory.archive == archive,
- SourcePackagePublishingHistory.distroseries == self,
- SourcePackagePublishingHistory.pocket == pocket,
- SourcePackagePublishingHistory.component == component,
- SourcePackagePublishingHistory.status ==
- PackagePublishingStatus.PUBLISHED,
- SourcePackagePublishingHistory.sourcepackagename ==
- SourcePackageName.id).order_by(SourcePackageName.name)
-
- def eager_load(spphs):
- # Preload everything which will be used by archivepublisher's
- # build_source_stanza_fields.
- load_related(Section, spphs, ["sectionID"])
- sprs = load_related(
- SourcePackageRelease, spphs, ["sourcepackagereleaseID"])
- load_related(SourcePackageName, sprs, ["sourcepackagenameID"])
- spr_ids = set(map(attrgetter("id"), sprs))
- sprfs = list(Store.of(self).find(
- SourcePackageReleaseFile,
- SourcePackageReleaseFile.sourcepackagereleaseID.is_in(
- spr_ids)).order_by(SourcePackageReleaseFile.libraryfileID))
- file_map = collections.defaultdict(list)
- for sprf in sprfs:
- file_map[sprf.sourcepackagerelease].append(sprf)
- for spr, files in file_map.items():
- get_property_cache(spr).files = files
- lfas = load_related(LibraryFileAlias, sprfs, ["libraryfileID"])
- load_related(LibraryFileContent, lfas, ["contentID"])
-
- return DecoratedResultSet(spphs, pre_iter_hook=eager_load)
-
- def getBinaryPackagePublishing(self, archtag, pocket, component, archive):
- """See `IDistroSeries`."""
- bpphs = Store.of(self).find(
- BinaryPackagePublishingHistory,
- DistroArchSeries.distroseries == self,
- DistroArchSeries.architecturetag == archtag,
- BinaryPackagePublishingHistory.archive == archive,
- BinaryPackagePublishingHistory.distroarchseries ==
- DistroArchSeries.id,
- BinaryPackagePublishingHistory.pocket == pocket,
- BinaryPackagePublishingHistory.component == component,
- BinaryPackagePublishingHistory.status ==
- PackagePublishingStatus.PUBLISHED,
- BinaryPackagePublishingHistory.binarypackagename ==
- BinaryPackageName.id).order_by(BinaryPackageName.name)
-
- def eager_load(bpphs):
- # Preload everything which will be used by archivepublisher's
- # build_binary_stanza_fields.
- load_related(Section, bpphs, ["sectionID"])
- bprs = load_related(
- BinaryPackageRelease, bpphs, ["binarypackagereleaseID"])
- bpbs = load_related(BinaryPackageBuild, bprs, ["buildID"])
- sprs = load_related(
- SourcePackageRelease, bpbs, ["source_package_release_id"])
- bpfs = load_referencing(
- BinaryPackageFile, bprs, ["binarypackagereleaseID"])
- file_map = collections.defaultdict(list)
- for bpf in bpfs:
- file_map[bpf.binarypackagerelease].append(bpf)
- for bpr, files in file_map.items():
- get_property_cache(bpr).files = files
- lfas = load_related(LibraryFileAlias, bpfs, ["libraryfileID"])
- load_related(LibraryFileContent, lfas, ["contentID"])
- load_related(SourcePackageName, sprs, ["sourcepackagenameID"])
- load_related(BinaryPackageName, bprs, ["binarypackagenameID"])
-
- return DecoratedResultSet(bpphs, pre_iter_hook=eager_load)
-
def getBuildRecords(self, build_state=None, name=None, pocket=None,
arch_tag=None, user=None, binary_only=True):
"""See IHasBuildRecords"""
diff --git a/lib/lp/registry/tests/test_distroseries.py b/lib/lp/registry/tests/test_distroseries.py
index f076ecd..a46cdcd 100644
--- a/lib/lp/registry/tests/test_distroseries.py
+++ b/lib/lp/registry/tests/test_distroseries.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2021 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Tests for distroseries."""
@@ -7,7 +7,6 @@ __all__ = [
'CurrentSourceReleasesMixin',
]
-from functools import partial
import json
from testtools.matchers import Equals
@@ -16,10 +15,6 @@ from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
from lp.app.interfaces.launchpad import ILaunchpadCelebrities
-from lp.archivepublisher.indices import (
- build_binary_stanza_fields,
- build_source_stanza_fields,
- )
from lp.registry.errors import NoSuchDistroSeries
from lp.registry.interfaces.distroseries import IDistroSeriesSet
from lp.registry.interfaces.pocket import PackagePublishingPocket
@@ -46,7 +41,6 @@ from lp.testing import (
api_url,
login,
person_logged_in,
- record_two_runs,
StormStatementRecorder,
TestCase,
TestCaseWithFactory,
@@ -584,47 +578,6 @@ class TestDistroSeriesPackaging(TestCaseWithFactory):
expected = ['translatable', 'linked', 'importabletranslatable']
self.assertEqual(expected, names)
- def test_getSourcePackagePublishing_query_count(self):
- # Check that the number of queries required to publish source
- # packages is constant in the number of source packages.
- def get_index_stanzas():
- for spp in self.series.getSourcePackagePublishing(
- PackagePublishingPocket.RELEASE, self.universe_component,
- self.series.main_archive):
- build_source_stanza_fields(
- spp.sourcepackagerelease, spp.component, spp.section)
-
- recorder1, recorder2 = record_two_runs(
- get_index_stanzas,
- partial(
- self.makeSeriesPackage, pocket=PackagePublishingPocket.RELEASE,
- status=PackagePublishingStatus.PUBLISHED),
- 5, 5)
- self.assertThat(recorder1, HasQueryCount(Equals(11)))
- self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
-
- def test_getBinaryPackagePublishing_query_count(self):
- # Check that the number of queries required to publish binary
- # packages is constant in the number of binary packages.
- def get_index_stanzas(das):
- for bpp in self.series.getBinaryPackagePublishing(
- das.architecturetag, PackagePublishingPocket.RELEASE,
- self.universe_component, self.series.main_archive):
- build_binary_stanza_fields(
- bpp.binarypackagerelease, bpp.component, bpp.section,
- bpp.priority, bpp.phased_update_percentage, False)
-
- das = self.factory.makeDistroArchSeries(distroseries=self.series)
- recorder1, recorder2 = record_two_runs(
- partial(get_index_stanzas, das),
- partial(
- self.makeSeriesBinaryPackage, das=das,
- pocket=PackagePublishingPocket.RELEASE,
- status=PackagePublishingStatus.PUBLISHED),
- 5, 5)
- self.assertThat(recorder1, HasQueryCount(Equals(15)))
- self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
-
class TestDistroSeriesWebservice(TestCaseWithFactory):
diff --git a/lib/lp/soyuz/interfaces/publishing.py b/lib/lp/soyuz/interfaces/publishing.py
index a1d5dc2..874d1a1 100644
--- a/lib/lp/soyuz/interfaces/publishing.py
+++ b/lib/lp/soyuz/interfaces/publishing.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Publishing interfaces."""
@@ -1133,6 +1133,32 @@ class IPublishingSet(Interface):
release in the given `archive`, `distroseries`, and `pocket`.
"""
+ def getSourcesForPublishing(archive, distroseries, pocket, component):
+ """Get source publications which are published in a given context.
+
+ :param archive: The `Archive` to search.
+ :param distroseries: The `DistroSeries` to search.
+ :param pocket: The `PackagePublishingPocket` to search.
+ :param component: The `Component` to search.
+ :return: A result set of `SourcePackagePublishingHistory` objects in
+ the given context and with the `PUBLISHED` status, ordered by
+ source package name, with associated publisher-relevant objects
+ preloaded.
+ """
+
+ def getBinariesForPublishing(archive, distroarchseries, pocket, component):
+ """Get binary publications which are published in a given context.
+
+ :param archive: The `Archive` to search.
+ :param distroarchseries: The `DistroArchSeries` to search.
+ :param pocket: The `PackagePublishingPocket` to search.
+ :param component: The `Component` to search.
+ :return: A result set of `BinaryPackagePublishingHistory` objects in
+ the given context and with the `PUBLISHED` status, ordered by
+ binary package name, with associated publisher-relevant objects
+ preloaded.
+ """
+
def getChangesFilesForSources(one_or_more_source_publications):
"""Return all changesfiles for each given source publication.
diff --git a/lib/lp/soyuz/model/publishing.py b/lib/lp/soyuz/model/publishing.py
index 421e649..ea0b012 100644
--- a/lib/lp/soyuz/model/publishing.py
+++ b/lib/lp/soyuz/model/publishing.py
@@ -1,4 +1,4 @@
-# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
__all__ = [
@@ -45,6 +45,7 @@ from lp.app.errors import NotFoundError
from lp.buildmaster.enums import BuildStatus
from lp.registry.interfaces.person import validate_public_person
from lp.registry.interfaces.pocket import PackagePublishingPocket
+from lp.registry.model.sourcepackagename import SourcePackageName
from lp.services.database import bulk
from lp.services.database.constants import UTC_NOW
from lp.services.database.datetimecol import UtcDateTimeCol
@@ -112,6 +113,7 @@ from lp.soyuz.model.files import (
BinaryPackageFile,
SourcePackageReleaseFile,
)
+from lp.soyuz.model.section import Section
from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
@@ -1511,6 +1513,81 @@ class PublishingSet:
active_publishing_status),
BinaryPackageRelease.architecturespecific == True)
+ def getSourcesForPublishing(self, archive, distroseries, pocket,
+ component):
+ """See `IPublishingSet`."""
+ spphs = IStore(SourcePackagePublishingHistory).find(
+ SourcePackagePublishingHistory,
+ SourcePackagePublishingHistory.archive == archive,
+ SourcePackagePublishingHistory.distroseries == distroseries,
+ SourcePackagePublishingHistory.pocket == pocket,
+ SourcePackagePublishingHistory.component == component,
+ SourcePackagePublishingHistory.status ==
+ PackagePublishingStatus.PUBLISHED,
+ SourcePackagePublishingHistory.sourcepackagename ==
+ SourcePackageName.id).order_by(SourcePackageName.name)
+
+ def eager_load(spphs):
+ # Preload everything which will be used by archivepublisher's
+ # build_source_stanza_fields.
+ bulk.load_related(Section, spphs, ["sectionID"])
+ sprs = bulk.load_related(
+ SourcePackageRelease, spphs, ["sourcepackagereleaseID"])
+ bulk.load_related(SourcePackageName, sprs, ["sourcepackagenameID"])
+ spr_ids = set(map(attrgetter("id"), sprs))
+ sprfs = list(IStore(SourcePackageReleaseFile).find(
+ SourcePackageReleaseFile,
+ SourcePackageReleaseFile.sourcepackagereleaseID.is_in(
+ spr_ids)).order_by(SourcePackageReleaseFile.libraryfileID))
+ file_map = defaultdict(list)
+ for sprf in sprfs:
+ file_map[sprf.sourcepackagerelease].append(sprf)
+ for spr, files in file_map.items():
+ get_property_cache(spr).files = files
+ lfas = bulk.load_related(
+ LibraryFileAlias, sprfs, ["libraryfileID"])
+ bulk.load_related(LibraryFileContent, lfas, ["contentID"])
+
+ return DecoratedResultSet(spphs, pre_iter_hook=eager_load)
+
+ def getBinariesForPublishing(self, archive, distroarchseries, pocket,
+ component):
+ """See `IPublishingSet`."""
+ bpphs = IStore(BinaryPackagePublishingHistory).find(
+ BinaryPackagePublishingHistory,
+ BinaryPackagePublishingHistory.archive == archive,
+ BinaryPackagePublishingHistory.distroarchseries ==
+ distroarchseries,
+ BinaryPackagePublishingHistory.pocket == pocket,
+ BinaryPackagePublishingHistory.component == component,
+ BinaryPackagePublishingHistory.status ==
+ PackagePublishingStatus.PUBLISHED,
+ BinaryPackagePublishingHistory.binarypackagename ==
+ BinaryPackageName.id).order_by(BinaryPackageName.name)
+
+ def eager_load(bpphs):
+ # Preload everything which will be used by archivepublisher's
+ # build_binary_stanza_fields.
+ bulk.load_related(Section, bpphs, ["sectionID"])
+ bprs = bulk.load_related(
+ BinaryPackageRelease, bpphs, ["binarypackagereleaseID"])
+ bpbs = bulk.load_related(BinaryPackageBuild, bprs, ["buildID"])
+ sprs = bulk.load_related(
+ SourcePackageRelease, bpbs, ["source_package_release_id"])
+ bpfs = bulk.load_referencing(
+ BinaryPackageFile, bprs, ["binarypackagereleaseID"])
+ file_map = defaultdict(list)
+ for bpf in bpfs:
+ file_map[bpf.binarypackagerelease].append(bpf)
+ for bpr, files in file_map.items():
+ get_property_cache(bpr).files = files
+ lfas = bulk.load_related(LibraryFileAlias, bpfs, ["libraryfileID"])
+ bulk.load_related(LibraryFileContent, lfas, ["contentID"])
+ bulk.load_related(SourcePackageName, sprs, ["sourcepackagenameID"])
+ bulk.load_related(BinaryPackageName, bprs, ["binarypackagenameID"])
+
+ return DecoratedResultSet(bpphs, pre_iter_hook=eager_load)
+
def getChangesFilesForSources(self, one_or_more_source_publications):
"""See `IPublishingSet`."""
# Avoid circular imports.
diff --git a/lib/lp/soyuz/tests/test_publishing.py b/lib/lp/soyuz/tests/test_publishing.py
index fbb19f0..d645ef8 100644
--- a/lib/lp/soyuz/tests/test_publishing.py
+++ b/lib/lp/soyuz/tests/test_publishing.py
@@ -1,9 +1,10 @@
-# Copyright 2009-2020 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2022 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Test native publication workflow for Soyuz. """
import datetime
+from functools import partial
import io
import operator
import os
@@ -20,6 +21,10 @@ from zope.security.proxy import removeSecurityProxy
from lp.app.errors import NotFoundError
from lp.archivepublisher.config import getPubConfig
from lp.archivepublisher.diskpool import DiskPool
+from lp.archivepublisher.indices import (
+ build_binary_stanza_fields,
+ build_source_stanza_fields,
+ )
from lp.buildmaster.enums import BuildStatus
from lp.buildmaster.interfaces.processor import IProcessorSet
from lp.registry.interfaces.distribution import IDistributionSet
@@ -1029,6 +1034,176 @@ class TestPublishingSetLite(TestCaseWithFactory):
"override the corresponding deb instead.",
debug_bpph.changeOverride, new_phased_update_percentage=20)
+ def makePublishedSourcePackage(self, series, pocket=None, status=None):
+ # Make a published source package.
+ name = self.factory.getUniqueUnicode()
+ sourcepackagename = self.factory.makeSourcePackageName(name)
+ component = getUtility(IComponentSet)["universe"]
+ spph = self.factory.makeSourcePackagePublishingHistory(
+ sourcepackagename=sourcepackagename, distroseries=series,
+ component=component, pocket=pocket, status=status)
+ source_package = self.factory.makeSourcePackage(
+ sourcepackagename=spph.sourcepackagename, distroseries=series)
+ spr = spph.sourcepackagerelease
+ for extension in ("dsc", "tar.gz"):
+ filename = "%s_%s.%s" % (spr.name, spr.version, extension)
+ spr.addFile(self.factory.makeLibraryFileAlias(
+ filename=filename, db_only=True))
+ return source_package
+
+ def test_getSourcesForPublishing(self):
+ # PublisherSet.getSourcesForPublishing returns all the ISPPH records
+ # in a given publishing context. It is used as part of publishing
+ # some types of archives.
+ # XXX cjwatson 2022-03-28: Detach test from sampledata.
+ ubuntu = getUtility(IDistributionSet)["ubuntu"]
+ hoary = ubuntu["hoary"]
+ component_main = getUtility(IComponentSet)["main"]
+ component_multiverse = getUtility(IComponentSet)["multiverse"]
+ debian_archive = getUtility(IDistributionSet)["debian"].main_archive
+ publishing_set = getUtility(IPublishingSet)
+
+ spphs = publishing_set.getSourcesForPublishing(
+ archive=hoary.main_archive, distroseries=hoary,
+ pocket=PackagePublishingPocket.RELEASE, component=component_main)
+ self.assertEqual(6, spphs.count())
+ self.assertContentEqual(
+ ["alsa-utils", "evolution", "libstdc++", "linux-source-2.6.15",
+ "netapplet", "pmount"],
+ {spph.sourcepackagerelease.name for spph in spphs})
+ self.assertEqual(
+ 0,
+ publishing_set.getSourcesForPublishing(
+ archive=hoary.main_archive, distroseries=hoary,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_multiverse).count())
+ self.assertEqual(
+ 0,
+ publishing_set.getSourcesForPublishing(
+ archive=hoary.main_archive, distroseries=hoary,
+ pocket=PackagePublishingPocket.BACKPORTS,
+ component=component_main).count())
+ self.assertEqual(
+ 0,
+ publishing_set.getSourcesForPublishing(
+ archive=debian_archive, distroseries=hoary,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_main).count())
+
+ def test_getSourcesForPublishing_query_count(self):
+ # Check that the number of queries required to publish source
+ # packages is constant in the number of source packages.
+ series = self.factory.makeDistroSeries()
+ archive = series.main_archive
+ component_universe = getUtility(IComponentSet)["universe"]
+
+ def get_index_stanzas():
+ for spp in getUtility(IPublishingSet).getSourcesForPublishing(
+ archive=archive, distroseries=series,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_universe):
+ build_source_stanza_fields(
+ spp.sourcepackagerelease, spp.component, spp.section)
+
+ recorder1, recorder2 = record_two_runs(
+ get_index_stanzas,
+ partial(
+ self.makePublishedSourcePackage, series=series,
+ pocket=PackagePublishingPocket.RELEASE,
+ status=PackagePublishingStatus.PUBLISHED),
+ 5, 5)
+ self.assertThat(recorder1, HasQueryCount(Equals(8)))
+ self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
+
+ def makePublishedBinaryPackage(self, das, pocket=None, status=None):
+ # Make a published binary package.
+ source = self.makePublishedSourcePackage(
+ das.distroseries, pocket=pocket, status=status)
+ spr = source.distinctreleases[0]
+ binarypackagename = self.factory.makeBinaryPackageName(source.name)
+ bpph = self.factory.makeBinaryPackagePublishingHistory(
+ binarypackagename=binarypackagename, distroarchseries=das,
+ component=spr.component, section_name=spr.section.name,
+ status=status, pocket=pocket, source_package_release=spr)
+ bpr = bpph.binarypackagerelease
+ filename = "%s_%s_%s.deb" % (
+ bpr.name, bpr.version, das.architecturetag)
+ bpr.addFile(self.factory.makeLibraryFileAlias(
+ filename=filename, db_only=True))
+ return bpph
+
+ def test_getBinariesForPublishing(self):
+ # PublisherSet.getBinariesForPublishing returns all the IBPPH
+ # records in a given publishing context. It is used as part of
+ # publishing some types of archives.
+ # XXX cjwatson 2022-03-28: Detach test from sampledata.
+ ubuntu = getUtility(IDistributionSet)["ubuntu"]
+ warty = ubuntu["warty"]
+ warty_i386 = warty["i386"]
+ warty_another = self.factory.makeDistroArchSeries(distroseries=warty)
+ component_main = getUtility(IComponentSet)["main"]
+ component_multiverse = getUtility(IComponentSet)["multiverse"]
+ debian_archive = getUtility(IDistributionSet)["debian"].main_archive
+ publishing_set = getUtility(IPublishingSet)
+
+ bpphs = publishing_set.getBinariesForPublishing(
+ archive=warty.main_archive, distroarchseries=warty_i386,
+ pocket=PackagePublishingPocket.RELEASE, component=component_main)
+ self.assertEqual(8, bpphs.count())
+ self.assertIn(
+ "mozilla-firefox",
+ {bpph.binarypackagerelease.name for bpph in bpphs})
+ self.assertEqual(
+ 0,
+ publishing_set.getBinariesForPublishing(
+ archive=warty.main_archive, distroarchseries=warty_another,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_main).count())
+ self.assertEqual(
+ 0,
+ publishing_set.getBinariesForPublishing(
+ archive=warty.main_archive, distroarchseries=warty_i386,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_multiverse).count())
+ self.assertEqual(
+ 0,
+ publishing_set.getBinariesForPublishing(
+ archive=warty.main_archive, distroarchseries=warty_i386,
+ pocket=PackagePublishingPocket.BACKPORTS,
+ component=component_main).count())
+ self.assertEqual(
+ 0,
+ publishing_set.getBinariesForPublishing(
+ archive=debian_archive, distroarchseries=warty_i386,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_main).count())
+
+ def test_getBinariesForPublishing_query_count(self):
+ # Check that the number of queries required to publish binary
+ # packages is constant in the number of binary packages.
+ das = self.factory.makeDistroArchSeries()
+ archive = das.main_archive
+ component_universe = getUtility(IComponentSet)["universe"]
+
+ def get_index_stanzas():
+ for bpp in getUtility(IPublishingSet).getBinariesForPublishing(
+ archive=archive, distroarchseries=das,
+ pocket=PackagePublishingPocket.RELEASE,
+ component=component_universe):
+ build_binary_stanza_fields(
+ bpp.binarypackagerelease, bpp.component, bpp.section,
+ bpp.priority, bpp.phased_update_percentage, False)
+
+ recorder1, recorder2 = record_two_runs(
+ get_index_stanzas,
+ partial(
+ self.makePublishedBinaryPackage, das=das,
+ pocket=PackagePublishingPocket.RELEASE,
+ status=PackagePublishingStatus.PUBLISHED),
+ 5, 5)
+ self.assertThat(recorder1, HasQueryCount(Equals(11)))
+ self.assertThat(recorder2, HasQueryCount.byEquality(recorder1))
+
class TestSourceDomination(TestNativePublishingBase):
"""Test SourcePackagePublishingHistory.supersede() operates correctly."""