1
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
"""Decorated `SourcePackagePublishingHistory` setup infrastructure.
6
`ArchiveSourcePublications` allows any callsite dealing with a set of
7
`SourcePackagePublishingHistory` to quickly fetch all the external
8
references needed to present them properly in the PPA pages.
14
'ArchiveSourcePublications',
17
from collections import defaultdict
19
from lazr.delegates import delegates
20
from zope.component import getUtility
22
from lp.registry.model.distroseries import DistroSeries
23
from lp.registry.model.sourcepackagename import SourcePackageName
24
from lp.services.database.lpstorm import IStore
25
from lp.services.librarian.browser import ProxiedLibraryFileAlias
26
from lp.soyuz.interfaces.publishing import (
28
ISourcePackagePublishingHistory,
30
from lp.soyuz.interfaces.sourcepackagerelease import ISourcePackageRelease
33
class ArchiveSourcePackageRelease:
34
"""Decorated `SourcePackageRelease` with cached 'upload_changesfile'.
36
It receives the related upload changesfile, so it doesn't need
39
delegates(ISourcePackageRelease)
41
def __init__(self, context, changesfile):
42
self.context = context
43
self._changesfile = changesfile
46
def upload_changesfile(self):
47
"""See `ISourcePackageRelease`."""
48
return self._changesfile
51
class ArchiveSourcePublication:
52
"""Delegates to `ISourcePackagePublishingHistory`.
54
It receives the expensive external references when it is created
55
and provide them as through the decorated interface transparently.
57
delegates(ISourcePackagePublishingHistory)
59
def __init__(self, context, changesfile, status_summary):
60
self.context = context
61
self._changesfile = changesfile
62
self._status_summary = status_summary
65
def sourcepackagerelease(self):
66
if self._changesfile is not None:
67
changesfile = ProxiedLibraryFileAlias(
68
self._changesfile, self.context.archive)
71
return ArchiveSourcePackageRelease(
72
self.context.sourcepackagerelease, changesfile)
74
def getStatusSummaryForBuilds(self):
75
"""See `ISourcePackagePublishingHistory`."""
76
return self._status_summary
79
class ArchiveSourcePublications:
80
"""`ArchiveSourcePublication` iterator."""
82
def __init__(self, source_publications):
83
"""Receives the list of target `SourcePackagePublishingHistory`."""
84
self._source_publications = list(source_publications)
87
def has_sources(self):
88
"""Whether or not there are sources to be processed."""
89
return len(self._source_publications) > 0
91
def getChangesFileBySource(self):
92
"""Map changesfiles by their corresponding source publications."""
93
publishing_set = getUtility(IPublishingSet)
94
changesfile_set = publishing_set.getChangesFilesForSources(
95
self._source_publications)
96
changesfile_mapping = {}
97
for entry in changesfile_set:
98
source, queue_record, source_release, changesfile, content = entry
99
changesfile_mapping[source] = changesfile
100
return changesfile_mapping
102
def __nonzero__(self):
103
"""Are there any sources to iterate?"""
104
return self.has_sources
107
"""`ArchiveSourcePublication` iterator."""
109
if not self.has_sources:
112
# Load the extra-information for all source publications.
113
# All of this code would be better on an object representing a set of
115
changesfiles_by_source = self.getChangesFileBySource()
116
# Source package names are used by setNewerDistroSeriesVersions:
117
# batch load the used source package names.
119
for spph in self._source_publications:
120
spn_ids.add(spph.sourcepackagerelease.sourcepackagenameID)
121
list(IStore(SourcePackageName).find(SourcePackageName,
122
SourcePackageName.id.is_in(spn_ids)))
123
DistroSeries.setNewerDistroSeriesVersions(self._source_publications)
124
# Load all the build status summaries at once.
125
publishing_set = getUtility(IPublishingSet)
126
archive_pub_ids = defaultdict(list)
127
for pub in self._source_publications:
128
archive_pub_ids[pub.archive].append(pub.id)
129
status_summaries = {}
130
for archive, pub_ids in archive_pub_ids.items():
131
status_summaries.update(
132
publishing_set.getBuildStatusSummariesForSourceIdsAndArchive(
135
# Build the decorated object with the information we have.
136
for pub in self._source_publications:
137
changesfile = changesfiles_by_source.get(pub, None)
138
status_summary = status_summaries[pub.id]
139
complete_pub = ArchiveSourcePublication(
140
pub, changesfile=changesfile, status_summary=status_summary)
141
results.append(complete_pub)