← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/dspc-out-of-distribution into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/dspc-out-of-distribution into lp:launchpad with lp:~wgrant/launchpad/dspc-out-of-distroseries as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/dspc-out-of-distribution/+merge/72675

Continuation of https://code.launchpad.net/~wgrant/launchpad/dspc-out-of-distroseries/+merge/72674, except moving DistributionSourcePackageCache management out of Distribution.
-- 
https://code.launchpad.net/~wgrant/launchpad/dspc-out-of-distribution/+merge/72675
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/dspc-out-of-distribution into lp:launchpad.
=== modified file 'cronscripts/update-pkgcache.py'
--- cronscripts/update-pkgcache.py	2011-08-24 06:31:26 +0000
+++ cronscripts/update-pkgcache.py	2011-08-24 06:31:27 +0000
@@ -15,6 +15,8 @@
 
 from lp.registry.interfaces.distribution import IDistributionSet
 from lp.services.scripts.base import LaunchpadCronScript
+from lp.soyuz.model.distributionsourcepackagecache import (
+    DistributionSourcePackageCache)
 from lp.soyuz.model.distroseriespackagecache import DistroSeriesPackageCache
 
 
@@ -50,10 +52,11 @@
         for distroseries in distribution.series:
             self.updateDistroSeriesCache(distroseries, archive)
 
-        distribution.removeOldCacheItems(archive, log=self.logger)
+        DistributionSourcePackageCache.removeOld(
+            distribution, archive, log=self.logger)
 
-        updates = distribution.updateCompleteSourcePackageCache(
-            archive=archive, ztm=self.txn, log=self.logger)
+        updates = DistributionSourcePackageCache.updateAll(
+            distribution, archive=archive, ztm=self.txn, log=self.logger)
 
         if updates > 0:
             self.txn.commit()

=== modified file 'lib/lp/registry/browser/tests/product-portlet-packages-view.txt'
--- lib/lp/registry/browser/tests/product-portlet-packages-view.txt	2011-05-27 19:53:20 +0000
+++ lib/lp/registry/browser/tests/product-portlet-packages-view.txt	2011-08-24 06:31:27 +0000
@@ -16,6 +16,8 @@
     >>> from lp.registry.interfaces.product import IProductSet
     >>> from lp.registry.interfaces.sourcepackagename import (
     ...     ISourcePackageNameSet)
+    >>> from lp.soyuz.model.distributionsourcepackagecache import (
+    ...     DistributionSourcePackageCache)
 
     >>> import transaction
     >>> from lp.services.log.logger import BufferLogger
@@ -28,8 +30,9 @@
     ...     transaction.commit()
     ...     reconnect_stores(config.statistician.dbuser)
     ...     ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
-    ...     ignore = ubuntu.updateCompleteSourcePackageCache(
-    ...         archive=ubuntu.main_archive, log=logger, ztm=transaction)
+    ...     ignore = DistributionSourcePackageCache.updateAll(
+    ...         ubuntu, archive=ubuntu.main_archive, log=logger,
+    ...         ztm=transaction)
     ...     transaction.commit()
     ...     reconnect_stores('launchpad')
     ...     # Get ubuntu, our product, and the sourcepackage name again

=== modified file 'lib/lp/registry/interfaces/distribution.py'
--- lib/lp/registry/interfaces/distribution.py	2011-08-23 07:05:30 +0000
+++ lib/lp/registry/interfaces/distribution.py	2011-08-24 06:31:27 +0000
@@ -491,46 +491,6 @@
         :return: list of `IDistroSeries`
         """
 
-    def getSourcePackageCaches(archive=None):
-        """The set of all source package info caches for this distribution.
-
-        If 'archive' is not given it will return all caches stored for the
-        distribution main archives (PRIMARY and PARTNER).
-        """
-
-    def removeOldCacheItems(archive, log):
-        """Delete any cache records for removed packages.
-
-        Also purges all existing cache records for disabled archives.
-
-        :param archive: target `IArchive`.
-        :param log: the context logger object able to print DEBUG level
-            messages.
-        """
-
-    def updateCompleteSourcePackageCache(archive, log, ztm, commit_chunk=500):
-        """Update the source package cache.
-
-        Consider every non-REMOVED sourcepackage and entirely skips updates
-        for disabled archives.
-
-        :param archive: target `IArchive`;
-        :param log: logger object for printing debug level information;
-        :param ztm:  transaction used for partial commits, every chunk of
-            'commit_chunk' updates is committed;
-        :param commit_chunk: number of updates before commit, defaults to 500.
-
-        :return the number packages updated done
-        """
-
-    def updateSourcePackageCache(sourcepackagename, archive, log):
-        """Update cached source package details.
-
-        Update cache details for a given ISourcePackageName, including
-        generated binarypackage names, summary and description fti.
-        'log' is required and only prints debug level information.
-        """
-
     @rename_parameters_as(text="source_match")
     @operation_parameters(
         text=TextLine(title=_("Source package name substring match"),

=== modified file 'lib/lp/registry/model/distribution.py'
--- lib/lp/registry/model/distribution.py	2011-08-23 07:05:30 +0000
+++ lib/lp/registry/model/distribution.py	2011-08-24 06:31:27 +0000
@@ -181,9 +181,6 @@
 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.distributionsourcepackagecache import (
-    DistributionSourcePackageCache,
-    )
 from lp.soyuz.model.distributionsourcepackagerelease import (
     DistributionSourcePackageRelease,
     )
@@ -1129,166 +1126,12 @@
         return getUtility(IBinaryPackageBuildSet).getBuildsByArchIds(
             self, arch_ids, build_state, name, pocket)
 
-    def getSourcePackageCaches(self, archive=None):
-        """See `IDistribution`."""
-        if archive is not None:
-            archives = [archive.id]
-        else:
-            archives = self.all_distro_archive_ids
-
-        caches = DistributionSourcePackageCache.select("""
-            distribution = %s AND
-            archive IN %s
-        """ % sqlvalues(self, archives),
-        orderBy="name",
-        prejoins=['sourcepackagename'])
-
-        return caches
-
-    def removeOldCacheItems(self, archive, log):
-        """See `IDistribution`."""
-
-        # Get the set of source package names to deal with.
-        spns = set(SourcePackageName.select("""
-            SourcePackagePublishingHistory.distroseries =
-                DistroSeries.id AND
-            DistroSeries.distribution = %s AND
-            Archive.id = %s AND
-            SourcePackagePublishingHistory.archive = Archive.id AND
-            SourcePackagePublishingHistory.sourcepackagerelease =
-                SourcePackageRelease.id AND
-            SourcePackageRelease.sourcepackagename =
-                SourcePackageName.id AND
-            SourcePackagePublishingHistory.dateremoved is NULL AND
-            Archive.enabled = TRUE
-            """ % sqlvalues(self, archive),
-            distinct=True,
-            clauseTables=[
-                'Archive',
-                'DistroSeries',
-                'SourcePackagePublishingHistory',
-                'SourcePackageRelease']))
-
-        # Remove the cache entries for packages we no longer publish.
-        for cache in self.getSourcePackageCaches(archive):
-            if cache.sourcepackagename not in spns:
-                log.debug(
-                    "Removing source cache for '%s' (%s)"
-                    % (cache.name, cache.id))
-                cache.destroySelf()
-
-    def updateCompleteSourcePackageCache(self, archive, log, ztm,
-                                         commit_chunk=500):
-        """See `IDistribution`."""
-        # Do not create cache entries for disabled archives.
-        if not archive.enabled:
-            return
-
-        # Get the set of source package names to deal with.
-        spns = list(SourcePackageName.select("""
-            SourcePackagePublishingHistory.distroseries =
-                DistroSeries.id AND
-            DistroSeries.distribution = %s AND
-            SourcePackagePublishingHistory.archive = %s AND
-            SourcePackagePublishingHistory.sourcepackagerelease =
-                SourcePackageRelease.id AND
-            SourcePackageRelease.sourcepackagename =
-                SourcePackageName.id AND
-            SourcePackagePublishingHistory.dateremoved is NULL
-            """ % sqlvalues(self, archive),
-            distinct=True,
-            orderBy="name",
-            clauseTables=['SourcePackagePublishingHistory', 'DistroSeries',
-                'SourcePackageRelease']))
-
-        number_of_updates = 0
-        chunk_size = 0
-        for spn in spns:
-            log.debug("Considering source '%s'" % spn.name)
-            self.updateSourcePackageCache(spn, archive, log)
-            chunk_size += 1
-            number_of_updates += 1
-            if chunk_size == commit_chunk:
-                chunk_size = 0
-                log.debug("Committing")
-                ztm.commit()
-
-        return number_of_updates
-
-    def updateSourcePackageCache(self, sourcepackagename, archive, log):
-        """See `IDistribution`."""
-
-        # Get the set of published sourcepackage releases.
-        sprs = list(SourcePackageRelease.select("""
-            SourcePackageRelease.sourcepackagename = %s AND
-            SourcePackageRelease.id =
-                SourcePackagePublishingHistory.sourcepackagerelease AND
-            SourcePackagePublishingHistory.distroseries =
-                DistroSeries.id AND
-            DistroSeries.distribution = %s AND
-            SourcePackagePublishingHistory.archive = %s AND
-            SourcePackagePublishingHistory.dateremoved is NULL
-            """ % sqlvalues(sourcepackagename, self, archive),
-            orderBy='id',
-            clauseTables=['SourcePackagePublishingHistory', 'DistroSeries'],
-            distinct=True))
-
-        if len(sprs) == 0:
-            log.debug("No sources releases found.")
-            return
-
-        # Find or create the cache entry.
-        cache = DistributionSourcePackageCache.selectOne("""
-            distribution = %s AND
-            archive = %s AND
-            sourcepackagename = %s
-            """ % sqlvalues(self, archive, sourcepackagename))
-        if cache is None:
-            log.debug("Creating new source cache entry.")
-            cache = DistributionSourcePackageCache(
-                archive=archive,
-                distribution=self,
-                sourcepackagename=sourcepackagename)
-
-        # Make sure the name is correct.
-        cache.name = sourcepackagename.name
-
-        # Get the sets of binary package names, summaries, descriptions.
-
-        # XXX Julian 2007-04-03:
-        # This bit of code needs fixing up, it is doing stuff that
-        # really needs to be done in SQL, such as sorting and uniqueness.
-        # This would also improve the performance.
-        binpkgnames = set()
-        binpkgsummaries = set()
-        binpkgdescriptions = set()
-        sprchangelog = set()
-        for spr in sprs:
-            log.debug("Considering source version %s" % spr.version)
-            # changelog may be empty, in which case we don't want to add it
-            # to the set as the join would fail below.
-            if spr.changelog_entry is not None:
-                sprchangelog.add(spr.changelog_entry)
-            binpkgs = BinaryPackageRelease.select("""
-                BinaryPackageRelease.build = BinaryPackageBuild.id AND
-                BinaryPackageBuild.source_package_release = %s
-                """ % sqlvalues(spr.id),
-                clauseTables=['BinaryPackageBuild'])
-            for binpkg in binpkgs:
-                log.debug("Considering binary '%s'" % binpkg.name)
-                binpkgnames.add(binpkg.name)
-                binpkgsummaries.add(binpkg.summary)
-                binpkgdescriptions.add(binpkg.description)
-
-        # Update the caches.
-        cache.binpkgnames = ' '.join(sorted(binpkgnames))
-        cache.binpkgsummaries = ' '.join(sorted(binpkgsummaries))
-        cache.binpkgdescriptions = ' '.join(sorted(binpkgdescriptions))
-        cache.changelog = ' '.join(sorted(sprchangelog))
-
     def searchSourcePackageCaches(
         self, text, has_packaging=None, publishing_distroseries=None):
         """See `IDistribution`."""
+        from lp.soyuz.model.distributionsourcepackagecache import (
+            DistributionSourcePackageCache,
+            )
         # The query below tries exact matching on the source package
         # name as well; this is because source package names are
         # notoriously bad for fti matching -- they can contain dots, or
@@ -1379,6 +1222,9 @@
         # This matches all DistributionSourcePackageCache rows that have
         # a source package that generated the BinaryPackageName that
         # we're searching for.
+        from lp.soyuz.model.distributionsourcepackagecache import (
+            DistributionSourcePackageCache,
+            )
         return (
             DistroSeries.distribution == self,
             DistroSeries.status != SeriesStatus.OBSOLETE,
@@ -1395,6 +1241,9 @@
 
     def searchBinaryPackages(self, package_name, exact_match=False):
         """See `IDistribution`."""
+        from lp.soyuz.model.distributionsourcepackagecache import (
+            DistributionSourcePackageCache,
+            )
         store = Store.of(self)
 
         select_spec = (DistributionSourcePackageCache,)

=== modified file 'lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt'
--- lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt	2011-08-24 06:31:26 +0000
+++ lib/lp/soyuz/doc/distroarchseriesbinarypackage.txt	2011-08-24 06:31:27 +0000
@@ -202,8 +202,10 @@
   >>> LaunchpadZopelessLayer.switchDbUser(config.statistician.dbuser)
 
   >>> from lp.services.log.logger import FakeLogger
-  >>> ubuntu.updateCompleteSourcePackageCache(
-  ...    archive=cprov.archive, ztm=LaunchpadZopelessLayer.txn,
+  >>> from lp.soyuz.model.distributionsourcepackagecache import (
+  ...     DistributionSourcePackageCache)
+  >>> DistributionSourcePackageCache.updateAll(
+  ...    ubuntu, archive=cprov.archive, ztm=LaunchpadZopelessLayer.txn,
   ...    log=FakeLogger())
   DEBUG ...
   DEBUG Considering source 'pmount'

=== modified file 'lib/lp/soyuz/doc/package-cache.txt'
--- lib/lp/soyuz/doc/package-cache.txt	2011-08-24 06:31:26 +0000
+++ lib/lp/soyuz/doc/package-cache.txt	2011-08-24 06:31:27 +0000
@@ -22,10 +22,12 @@
    for name, binpkgnames, binpkgsummaries and binpkgdescriptions.
 
   >>> from lp.registry.interfaces.distribution import IDistributionSet
+  >>> from lp.soyuz.model.distributionsourcepackagecache import (
+  ...     DistributionSourcePackageCache)
 
   >>> ubuntu = getUtility(IDistributionSet)['ubuntu']
 
-  >>> ubuntu_caches = ubuntu.getSourcePackageCaches()
+  >>> ubuntu_caches = DistributionSourcePackageCache._find(ubuntu)
 
   >>> ubuntu_caches.count()
   10
@@ -110,9 +112,6 @@
   >>> ubuntu.searchSourcePackages('foobar').count()
   1
 
-  >>> from lp.soyuz.model.distributionsourcepackagecache import (
-  ...    DistributionSourcePackageCache)
-
   >>> foobar_cache = DistributionSourcePackageCache.selectOneBy(
   ...     archive=ubuntu.main_archive, distribution=ubuntu, name='foobar')
 
@@ -125,7 +124,8 @@
 Let's use a fake logger object:
 
   >>> from lp.services.log.logger import FakeLogger
-  >>> ubuntu.removeOldCacheItems(archive=ubuntu.main_archive, log=FakeLogger())
+  >>> DistributionSourcePackageCache.removeOld(
+  ...     ubuntu, archive=ubuntu.main_archive, log=FakeLogger())
   DEBUG Removing source cache for 'foobar' (10)
 
   >>> import transaction
@@ -160,8 +160,9 @@
 
 We can invoke the cache updater directly on IDistroSeries:
 
-  >>> updates = ubuntu.updateCompleteSourcePackageCache(
-  ...    archive=ubuntu.main_archive, ztm=transaction, log=FakeLogger())
+  >>> updates = DistributionSourcePackageCache.updateAll(
+  ...    ubuntu, archive=ubuntu.main_archive, ztm=transaction,
+  ...    log=FakeLogger())
   DEBUG ...
   DEBUG Considering source 'cdrkit'
   DEBUG Creating new source cache entry.
@@ -214,9 +215,6 @@
   >>> warty.searchPackages('foobar').count()
   1
 
-  >>> from lp.soyuz.model.distroseriespackagecache import (
-  ...      DistroSeriesPackageCache)
-
   >>> foobar_bin_cache = DistroSeriesPackageCache.selectOneBy(
   ...     archive=ubuntu.main_archive, distroseries=warty, name='foobar')
 
@@ -357,8 +355,8 @@
 If we populate the package caches and update the archive caches, the
 same queries work, pointing to Celso's PPA.
 
-  >>> source_updates = ubuntu.updateCompleteSourcePackageCache(
-  ...    archive=cprov.archive, ztm=transaction, log=FakeLogger())
+  >>> source_updates = DistributionSourcePackageCache.updateAll(
+  ...    ubuntu, archive=cprov.archive, ztm=transaction, log=FakeLogger())
   DEBUG ...
   DEBUG Considering source 'pmount'
   ...
@@ -704,9 +702,10 @@
     >>> from lp.services.log.logger import BufferLogger
     >>> logger = BufferLogger()
     >>> def rebuild_caches(archive):
-    ...     ubuntu.removeOldCacheItems(archive=archive, log=logger)
-    ...     ubuntu.updateCompleteSourcePackageCache(
-    ...         archive=archive, ztm=transaction, log=logger)
+    ...     DistributionSourcePackageCache.removeOld(
+    ...         ubuntu, archive=archive, log=logger)
+    ...     DistributionSourcePackageCache.updateAll(
+    ...         ubuntu, archive=archive, ztm=transaction, log=logger)
     ...     for series in ubuntu.series:
     ...         DistroSeriesPackageCache.removeOld(
     ...             series, archive=archive, log=logger)

=== modified file 'lib/lp/soyuz/model/archive.py'
--- lib/lp/soyuz/model/archive.py	2011-08-24 06:31:26 +0000
+++ lib/lp/soyuz/model/archive.py	2011-08-24 06:31:27 +0000
@@ -186,9 +186,6 @@
     BinaryPackageReleaseDownloadCount,
     )
 from lp.soyuz.model.component import Component
-from lp.soyuz.model.distributionsourcepackagecache import (
-    DistributionSourcePackageCache,
-    )
 from lp.soyuz.model.files import (
     BinaryPackageFile,
     SourcePackageReleaseFile,
@@ -909,6 +906,9 @@
 
     def updateArchiveCache(self):
         """See `IArchive`."""
+        from lp.soyuz.model.distributionsourcepackagecache import (
+            DistributionSourcePackageCache,
+            )
         from lp.soyuz.model.distroseriespackagecache import (
             DistroSeriesPackageCache)
         # Compiled regexp to remove puntication.

=== modified file 'lib/lp/soyuz/model/distributionsourcepackagecache.py'
--- lib/lp/soyuz/model/distributionsourcepackagecache.py	2010-08-20 20:31:18 +0000
+++ lib/lp/soyuz/model/distributionsourcepackagecache.py	2011-08-24 06:31:27 +0000
@@ -6,16 +6,28 @@
 __metaclass__ = type
 __all__ = ['DistributionSourcePackageCache', ]
 
+from operator import itemgetter
+
 from sqlobject import (
     ForeignKey,
     StringCol,
     )
 from zope.interface import implements
 
-from canonical.database.sqlbase import SQLBase
+from canonical.database.sqlbase import (
+    SQLBase,
+    sqlvalues,
+    )
+from canonical.launchpad.components.decoratedresultset import (
+    DecoratedResultSet,
+    )
+from canonical.launchpad.interfaces.lpstorm import IStore
+from lp.registry.model.sourcepackagename import SourcePackageName
 from lp.soyuz.interfaces.distributionsourcepackagecache import (
     IDistributionSourcePackageCache,
     )
+from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease
+from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
 
 
 class DistributionSourcePackageCache(SQLBase):
@@ -46,3 +58,190 @@
         return DistributionSourcePackage(self.distribution,
             self.sourcepackagename)
 
+    @classmethod
+    def _find(cls, distro, archive=None):
+        """The set of all source package info caches for this distribution.
+
+        If 'archive' is not given it will return all caches stored for the
+        distribution main archives (PRIMARY and PARTNER).
+        """
+        if archive is not None:
+            archives = [archive.id]
+        else:
+            archives = distro.all_distro_archive_ids
+
+        result = IStore(DistributionSourcePackageCache).find(
+            (DistributionSourcePackageCache, SourcePackageName),
+            DistributionSourcePackageCache.distribution == distro,
+            DistributionSourcePackageCache.archiveID.is_in(archives),
+            SourcePackageName.id ==
+                DistributionSourcePackageCache.sourcepackagenameID,
+            ).order_by(DistributionSourcePackageCache.name)
+        return DecoratedResultSet(result, itemgetter(0))
+
+    @classmethod
+    def removeOld(cls, distro, archive, log):
+        """Delete any cache records for removed packages.
+
+        Also purges all existing cache records for disabled archives.
+
+        :param archive: target `IArchive`.
+        :param log: the context logger object able to print DEBUG level
+            messages.
+        """
+
+        # Get the set of source package names to deal with.
+        spns = set(SourcePackageName.select("""
+            SourcePackagePublishingHistory.distroseries =
+                DistroSeries.id AND
+            DistroSeries.distribution = %s AND
+            Archive.id = %s AND
+            SourcePackagePublishingHistory.archive = Archive.id AND
+            SourcePackagePublishingHistory.sourcepackagerelease =
+                SourcePackageRelease.id AND
+            SourcePackageRelease.sourcepackagename =
+                SourcePackageName.id AND
+            SourcePackagePublishingHistory.dateremoved is NULL AND
+            Archive.enabled = TRUE
+            """ % sqlvalues(distro, archive),
+            distinct=True,
+            clauseTables=[
+                'Archive',
+                'DistroSeries',
+                'SourcePackagePublishingHistory',
+                'SourcePackageRelease']))
+
+        # Remove the cache entries for packages we no longer publish.
+        for cache in cls._find(distro, archive):
+            if cache.sourcepackagename not in spns:
+                log.debug(
+                    "Removing source cache for '%s' (%s)"
+                    % (cache.name, cache.id))
+                cache.destroySelf()
+
+    @classmethod
+    def _update(cls, distro, sourcepackagename, archive, log):
+        """Update cached source package details.
+
+        Update cache details for a given ISourcePackageName, including
+        generated binarypackage names, summary and description fti.
+        'log' is required and only prints debug level information.
+        """
+
+        # Get the set of published sourcepackage releases.
+        sprs = list(SourcePackageRelease.select("""
+            SourcePackageRelease.sourcepackagename = %s AND
+            SourcePackageRelease.id =
+                SourcePackagePublishingHistory.sourcepackagerelease AND
+            SourcePackagePublishingHistory.distroseries =
+                DistroSeries.id AND
+            DistroSeries.distribution = %s AND
+            SourcePackagePublishingHistory.archive = %s AND
+            SourcePackagePublishingHistory.dateremoved is NULL
+            """ % sqlvalues(sourcepackagename, distro, archive),
+            orderBy='id',
+            clauseTables=['SourcePackagePublishingHistory', 'DistroSeries'],
+            distinct=True))
+
+        if len(sprs) == 0:
+            log.debug("No sources releases found.")
+            return
+
+        # Find or create the cache entry.
+        cache = DistributionSourcePackageCache.selectOne("""
+            distribution = %s AND
+            archive = %s AND
+            sourcepackagename = %s
+            """ % sqlvalues(distro, archive, sourcepackagename))
+        if cache is None:
+            log.debug("Creating new source cache entry.")
+            cache = DistributionSourcePackageCache(
+                archive=archive,
+                distribution=distro,
+                sourcepackagename=sourcepackagename)
+
+        # Make sure the name is correct.
+        cache.name = sourcepackagename.name
+
+        # Get the sets of binary package names, summaries, descriptions.
+
+        # XXX Julian 2007-04-03:
+        # This bit of code needs fixing up, it is doing stuff that
+        # really needs to be done in SQL, such as sorting and uniqueness.
+        # This would also improve the performance.
+        binpkgnames = set()
+        binpkgsummaries = set()
+        binpkgdescriptions = set()
+        sprchangelog = set()
+        for spr in sprs:
+            log.debug("Considering source version %s" % spr.version)
+            # changelog may be empty, in which case we don't want to add it
+            # to the set as the join would fail below.
+            if spr.changelog_entry is not None:
+                sprchangelog.add(spr.changelog_entry)
+            binpkgs = BinaryPackageRelease.select("""
+                BinaryPackageRelease.build = BinaryPackageBuild.id AND
+                BinaryPackageBuild.source_package_release = %s
+                """ % sqlvalues(spr.id),
+                clauseTables=['BinaryPackageBuild'])
+            for binpkg in binpkgs:
+                log.debug("Considering binary '%s'" % binpkg.name)
+                binpkgnames.add(binpkg.name)
+                binpkgsummaries.add(binpkg.summary)
+                binpkgdescriptions.add(binpkg.description)
+
+        # Update the caches.
+        cache.binpkgnames = ' '.join(sorted(binpkgnames))
+        cache.binpkgsummaries = ' '.join(sorted(binpkgsummaries))
+        cache.binpkgdescriptions = ' '.join(sorted(binpkgdescriptions))
+        cache.changelog = ' '.join(sorted(sprchangelog))
+
+    @classmethod
+    def updateAll(cls, distro, archive, log, ztm, commit_chunk=500):
+        """Update the source package cache.
+
+        Consider every non-REMOVED sourcepackage and entirely skips updates
+        for disabled archives.
+
+        :param archive: target `IArchive`;
+        :param log: logger object for printing debug level information;
+        :param ztm:  transaction used for partial commits, every chunk of
+            'commit_chunk' updates is committed;
+        :param commit_chunk: number of updates before commit, defaults to 500.
+
+        :return the number packages updated done
+        """
+        # Do not create cache entries for disabled archives.
+        if not archive.enabled:
+            return
+
+        # Get the set of source package names to deal with.
+        spns = list(SourcePackageName.select("""
+            SourcePackagePublishingHistory.distroseries =
+                DistroSeries.id AND
+            DistroSeries.distribution = %s AND
+            SourcePackagePublishingHistory.archive = %s AND
+            SourcePackagePublishingHistory.sourcepackagerelease =
+                SourcePackageRelease.id AND
+            SourcePackageRelease.sourcepackagename =
+                SourcePackageName.id AND
+            SourcePackagePublishingHistory.dateremoved is NULL
+            """ % sqlvalues(distro, archive),
+            distinct=True,
+            orderBy="name",
+            clauseTables=['SourcePackagePublishingHistory', 'DistroSeries',
+                'SourcePackageRelease']))
+
+        number_of_updates = 0
+        chunk_size = 0
+        for spn in spns:
+            log.debug("Considering source '%s'" % spn.name)
+            cls._update(distro, spn, archive, log)
+            chunk_size += 1
+            number_of_updates += 1
+            if chunk_size == commit_chunk:
+                chunk_size = 0
+                log.debug("Committing")
+                ztm.commit()
+
+        return number_of_updates