Merge lp:~wgrant/launchpad/bug-728836 into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: Robert Collins
Approved revision: no longer in the source branch.
Merged at revision: 12537
Proposed branch: lp:~wgrant/launchpad/bug-728836
Merge into: lp:launchpad
Diff against target: 574 lines (+286/-77)
9 files modified
lib/lp/registry/interfaces/distroseries.py (+1/-1)
lib/lp/registry/model/distroseries.py (+2/-2)
lib/lp/soyuz/interfaces/binarypackagerelease.py (+1/-0)
lib/lp/soyuz/interfaces/publishing.py (+21/-4)
lib/lp/soyuz/model/archive.py (+6/-1)
lib/lp/soyuz/model/publishing.py (+139/-61)
lib/lp/soyuz/model/queue.py (+3/-6)
lib/lp/soyuz/tests/test_publishing.py (+111/-0)
lib/lp/testing/factory.py (+2/-2)
To merge this branch: bzr merge lp:~wgrant/launchpad/bug-728836
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
Review via email: mp+52355@code.launchpad.net

Commit message

[r=lifeless][bug=728836] Optimise PublishingSet.copyBinariesTo to O(1) queries.

Description of the change

This branch improves the scalability of Archive:+copy-packages and Archive.syncSource by optimising PublishingSet.copyBinariesTo to a constant query count. The queries produced by this method can be seen clearly in OOPS-1858O745: it makes up all of the 2nd and 3rd most repeated queries, and much of the 5th (the 1st and 4th have already been addressed by another branch). Each of those cases is now reduced to a single query per source.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

Couple of bits that can be improved.

302 + if len(needed) == 0:
'if not needed:' would be clearer.

the 8 line generator expression is getting tricky to read.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/registry/interfaces/distroseries.py'
--- lib/lp/registry/interfaces/distroseries.py 2011-02-24 15:30:54 +0000
+++ lib/lp/registry/interfaces/distroseries.py 2011-03-07 07:05:26 +0000
@@ -767,7 +767,7 @@
767 """767 """
768768
769 def newArch(architecturetag, processorfamily, official, owner,769 def newArch(architecturetag, processorfamily, official, owner,
770 supports_virtualized=False):770 supports_virtualized=False, enabled=True):
771 """Create a new port or DistroArchSeries for this DistroSeries."""771 """Create a new port or DistroArchSeries for this DistroSeries."""
772772
773 def copyTranslationsFromParent(ztm):773 def copyTranslationsFromParent(ztm):
774774
=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py 2011-02-22 08:20:21 +0000
+++ lib/lp/registry/model/distroseries.py 2011-03-07 07:05:26 +0000
@@ -1459,12 +1459,12 @@
1459 return DecoratedResultSet(package_caches, result_to_dsbp)1459 return DecoratedResultSet(package_caches, result_to_dsbp)
14601460
1461 def newArch(self, architecturetag, processorfamily, official, owner,1461 def newArch(self, architecturetag, processorfamily, official, owner,
1462 supports_virtualized=False):1462 supports_virtualized=False, enabled=True):
1463 """See `IDistroSeries`."""1463 """See `IDistroSeries`."""
1464 distroarchseries = DistroArchSeries(1464 distroarchseries = DistroArchSeries(
1465 architecturetag=architecturetag, processorfamily=processorfamily,1465 architecturetag=architecturetag, processorfamily=processorfamily,
1466 official=official, distroseries=self, owner=owner,1466 official=official, distroseries=self, owner=owner,
1467 supports_virtualized=supports_virtualized)1467 supports_virtualized=supports_virtualized, enabled=enabled)
1468 return distroarchseries1468 return distroarchseries
14691469
1470 def newMilestone(self, name, dateexpected=None, summary=None,1470 def newMilestone(self, name, dateexpected=None, summary=None,
14711471
=== modified file 'lib/lp/soyuz/interfaces/binarypackagerelease.py'
--- lib/lp/soyuz/interfaces/binarypackagerelease.py 2011-02-23 20:26:53 +0000
+++ lib/lp/soyuz/interfaces/binarypackagerelease.py 2011-03-07 07:05:26 +0000
@@ -44,6 +44,7 @@
44class IBinaryPackageRelease(Interface):44class IBinaryPackageRelease(Interface):
45 id = Int(title=_('ID'), required=True)45 id = Int(title=_('ID'), required=True)
46 binarypackagename = Int(required=True)46 binarypackagename = Int(required=True)
47 binarypackagenameID = Int(required=True)
47 version = TextLine(required=True, constraint=valid_debian_version)48 version = TextLine(required=True, constraint=valid_debian_version)
48 summary = Text(required=True)49 summary = Text(required=True)
49 description = Text(required=True)50 description = Text(required=True)
5051
=== modified file 'lib/lp/soyuz/interfaces/publishing.py'
--- lib/lp/soyuz/interfaces/publishing.py 2011-03-03 00:43:44 +0000
+++ lib/lp/soyuz/interfaces/publishing.py 2011-03-07 07:05:26 +0000
@@ -678,6 +678,7 @@
678 required=False, readonly=False,678 required=False, readonly=False,
679 ),679 ),
680 exported_as="distro_arch_series")680 exported_as="distro_arch_series")
681 distroseries = Attribute("The distroseries being published into")
681 component = Int(682 component = Int(
682 title=_('The component being published into'),683 title=_('The component being published into'),
683 required=False, readonly=False,684 required=False, readonly=False,
@@ -878,7 +879,25 @@
878 publishing histories.879 publishing histories.
879 """880 """
880881
881 def publishBinary(archive, binarypackagerelease, distroarchseries,882 def publishBinaries(archive, distroseries, pocket, binaries):
883 """Efficiently publish multiple BinaryPackageReleases in an Archive.
884
885 Creates `IBinaryPackagePublishingHistory` records for each binary,
886 handling architecture-independent and debug packages, avoiding
887 creation of duplicate publications, and leaving disabled
888 architectures alone.
889
890 :param archive: The target `IArchive`.
891 :param distroseries: The target `IDistroSeries`.
892 :param pocket: The target `PackagePublishingPocket`.
893 :param binaries: A dict mapping `BinaryPackageReleases` to their
894 desired overrides as (`Component`, `Section`,
895 `PackagePublishingPriority`) tuples.
896
897 :return: A list of new `IBinaryPackagePublishingHistory` records.
898 """
899
900 def publishBinary(archive, binarypackagerelease, distroseries,
882 component, section, priority, pocket):901 component, section, priority, pocket):
883 """Publish a `BinaryPackageRelease` in an archive.902 """Publish a `BinaryPackageRelease` in an archive.
884903
@@ -890,9 +909,7 @@
890909
891 :param archive: The target `IArchive`.910 :param archive: The target `IArchive`.
892 :param binarypackagerelease: The `IBinaryPackageRelease` to copy.911 :param binarypackagerelease: The `IBinaryPackageRelease` to copy.
893 :param distroarchseries: An `IDistroArchSeries`. If the binary is912 :param distroseries: An `IDistroSeries`.
894 architecture-independent, it will be published to all enabled
895 architectures in this series.
896 :param component: The target `IComponent`.913 :param component: The target `IComponent`.
897 :param section: The target `ISection`.914 :param section: The target `ISection`.
898 :param priority: The target `PackagePublishingPriority`.915 :param priority: The target `PackagePublishingPriority`.
899916
=== modified file 'lib/lp/soyuz/model/archive.py'
--- lib/lp/soyuz/model/archive.py 2011-03-03 03:13:13 +0000
+++ lib/lp/soyuz/model/archive.py 2011-03-07 07:05:26 +0000
@@ -386,7 +386,7 @@
386 query, clauseTables=clauseTables, orderBy=orderBy)386 query, clauseTables=clauseTables, orderBy=orderBy)
387 return dependencies387 return dependencies
388388
389 @property389 @cachedproperty
390 def debug_archive(self):390 def debug_archive(self):
391 """See `IArchive`."""391 """See `IArchive`."""
392 if self.purpose == ArchivePurpose.PRIMARY:392 if self.purpose == ArchivePurpose.PRIMARY:
@@ -1933,6 +1933,11 @@
1933 if enabled == False:1933 if enabled == False:
1934 new_archive.disable()1934 new_archive.disable()
19351935
1936 if purpose == ArchivePurpose.DEBUG:
1937 if distribution.main_archive is not None:
1938 del get_property_cache(
1939 distribution.main_archive).debug_archive
1940
1936 # Private teams cannot have public PPAs.1941 # Private teams cannot have public PPAs.
1937 if owner.visibility == PersonVisibility.PRIVATE:1942 if owner.visibility == PersonVisibility.PRIVATE:
1938 new_archive.buildd_secret = create_unique_token_for_table(1943 new_archive.buildd_secret = create_unique_token_for_table(
19391944
=== modified file 'lib/lp/soyuz/model/publishing.py'
--- lib/lp/soyuz/model/publishing.py 2011-03-03 08:01:34 +0000
+++ lib/lp/soyuz/model/publishing.py 2011-03-07 07:05:26 +0000
@@ -29,8 +29,10 @@
29 StringCol,29 StringCol,
30 )30 )
31from storm.expr import (31from storm.expr import (
32 And,
32 Desc,33 Desc,
33 LeftJoin,34 LeftJoin,
35 Or,
34 Sum,36 Sum,
35 )37 )
36from storm.store import Store38from storm.store import Store
@@ -63,7 +65,6 @@
63 IStoreSelector,65 IStoreSelector,
64 MAIN_STORE,66 MAIN_STORE,
65 )67 )
66from lp.app.errors import NotFoundError
67from lp.buildmaster.enums import BuildStatus68from lp.buildmaster.enums import BuildStatus
68from lp.buildmaster.model.buildfarmjob import BuildFarmJob69from lp.buildmaster.model.buildfarmjob import BuildFarmJob
69from lp.buildmaster.model.packagebuild import PackageBuild70from lp.buildmaster.model.packagebuild import PackageBuild
@@ -121,7 +122,7 @@
121 'pool', poolify(source_name, component_name))122 'pool', poolify(source_name, component_name))
122123
123124
124def maybe_override_component(archive, distroseries, component):125def get_component(archive, distroseries, component):
125 """Override the component to fit in the archive, if possible.126 """Override the component to fit in the archive, if possible.
126127
127 If the archive has a default component, and it forbids use of the128 If the archive has a default component, and it forbids use of the
@@ -136,6 +137,22 @@
136 return component137 return component
137138
138139
140def get_archive(archive, bpr):
141 """Get the archive in which this binary should be published.
142
143 Debug packages live in a DEBUG archive instead of a PRIMARY archive.
144 This helper implements that override.
145 """
146 if bpr.binpackageformat == BinaryPackageFormat.DDEB:
147 debug_archive = archive.debug_archive
148 if debug_archive is None:
149 raise QueueInconsistentStateError(
150 "Could not find the corresponding DEBUG archive "
151 "for %s" % (archive.displayname))
152 archive = debug_archive
153 return archive
154
155
139class FilePublishingBase:156class FilePublishingBase:
140 """Base class to publish files in the archive."""157 """Base class to publish files in the archive."""
141158
@@ -914,18 +931,23 @@
914 binarypackagepublishing=self).prejoin(preJoins)931 binarypackagepublishing=self).prejoin(preJoins)
915932
916 @property933 @property
934 def distroseries(self):
935 """See `IBinaryPackagePublishingHistory`"""
936 return self.distroarchseries.distroseries
937
938 @property
917 def binary_package_name(self):939 def binary_package_name(self):
918 """See `ISourcePackagePublishingHistory`"""940 """See `IBinaryPackagePublishingHistory`"""
919 return self.binarypackagerelease.name941 return self.binarypackagerelease.name
920942
921 @property943 @property
922 def binary_package_version(self):944 def binary_package_version(self):
923 """See `ISourcePackagePublishingHistory`"""945 """See `IBinaryPackagePublishingHistory`"""
924 return self.binarypackagerelease.version946 return self.binarypackagerelease.version
925947
926 @property948 @property
927 def priority_name(self):949 def priority_name(self):
928 """See `ISourcePackagePublishingHistory`"""950 """See `IBinaryPackagePublishingHistory`"""
929 return self.priority.name951 return self.priority.name
930952
931 @property953 @property
@@ -1245,6 +1267,42 @@
1245 self.requestDeletion(removed_by, removal_comment)1267 self.requestDeletion(removed_by, removal_comment)
12461268
12471269
1270def expand_binary_requests(distroseries, binaries):
1271 """Architecture-expand a dict of binary publication requests.
1272
1273 For architecture-independent binaries, a tuple will be returned for each
1274 enabled architecture in the series.
1275 For architecture-dependent binaries, a tuple will be returned only for the
1276 architecture corresponding to the build architecture, if it exists and is
1277 enabled.
1278
1279 :param binaries: A dict mapping `BinaryPackageReleases` to tuples of their
1280 desired overrides.
1281
1282 :return: The binaries and the architectures in which they should be
1283 published, as a sequence of (`DistroArchSeries`,
1284 `BinaryPackageRelease`, (overrides)) tuples.
1285 """
1286
1287 archs = list(distroseries.enabled_architectures)
1288 arch_map = dict((arch.architecturetag, arch) for arch in archs)
1289
1290 expanded = []
1291 for bpr, overrides in binaries.iteritems():
1292 if bpr.architecturespecific:
1293 # Find the DAS in this series corresponding to the original
1294 # build arch tag. If it does not exist or is disabled, we should
1295 # not publish.
1296 target_arch = arch_map.get(
1297 bpr.build.distro_arch_series.architecturetag)
1298 target_archs = [target_arch] if target_arch is not None else []
1299 else:
1300 target_archs = archs
1301 for target_arch in target_archs:
1302 expanded.append((target_arch, bpr, overrides))
1303 return expanded
1304
1305
1248class PublishingSet:1306class PublishingSet:
1249 """Utilities for manipulating publications in batches."""1307 """Utilities for manipulating publications in batches."""
12501308
@@ -1252,61 +1310,82 @@
12521310
1253 def copyBinariesTo(self, binaries, distroseries, pocket, archive):1311 def copyBinariesTo(self, binaries, distroseries, pocket, archive):
1254 """See `IPublishingSet`."""1312 """See `IPublishingSet`."""
1255 secure_copies = []1313 return self.publishBinaries(
1256 for binary in binaries:1314 archive, distroseries, pocket,
1257 # This will go wrong if nominatedarchindep gets deleted in a1315 dict(
1258 # future series -- it will attempt to retrieve i386 from the1316 (bpph.binarypackagerelease, (bpph.component, bpph.section,
1259 # new series, fail, and skip the publication instead of1317 bpph.priority)) for bpph in binaries))
1260 # publishing the remaining archs.1318
1261 try:1319 def publishBinaries(self, archive, distroseries, pocket,
1262 build = binary.binarypackagerelease.build1320 binaries):
1263 target_architecture = distroseries[1321 """See `IPublishingSet`."""
1264 build.distro_arch_series.architecturetag]1322 # Expand the dict of binaries into a list of tuples including the
1265 except NotFoundError:1323 # architecture.
1266 continue1324 expanded = expand_binary_requests(distroseries, binaries)
1267 if not target_architecture.enabled:1325
1268 continue1326 # Find existing publications.
1269 secure_copies.extend(1327 # We should really be able to just compare BPR.id, but
1270 getUtility(IPublishingSet).publishBinary(1328 # CopyChecker doesn't seem to ensure that there are no
1271 archive, binary.binarypackagerelease, target_architecture,1329 # conflicting binaries from other sources.
1272 binary.component, binary.section, binary.priority,1330 def make_package_condition(archive, das, bpr):
1273 pocket))1331 return And(
1274 return secure_copies1332 BinaryPackagePublishingHistory.archiveID ==
12751333 get_archive(archive, bpr).id,
1276 def publishBinary(self, archive, binarypackagerelease, distroarchseries,1334 BinaryPackagePublishingHistory.distroarchseriesID == das.id,
1335 BinaryPackageRelease.binarypackagenameID ==
1336 bpr.binarypackagenameID,
1337 BinaryPackageRelease.version == bpr.version,
1338 )
1339 candidates = (
1340 make_package_condition(archive, das, bpr)
1341 for das, bpr, overrides in expanded)
1342 already_published = IMasterStore(BinaryPackagePublishingHistory).find(
1343 (BinaryPackagePublishingHistory.distroarchseriesID,
1344 BinaryPackageRelease.binarypackagenameID,
1345 BinaryPackageRelease.version),
1346 BinaryPackagePublishingHistory.pocket == pocket,
1347 BinaryPackagePublishingHistory.status.is_in(
1348 active_publishing_status),
1349 BinaryPackageRelease.id ==
1350 BinaryPackagePublishingHistory.binarypackagereleaseID,
1351 Or(*candidates)).config(distinct=True)
1352 already_published = frozenset(already_published)
1353
1354 needed = [
1355 (das, bpr, overrides) for (das, bpr, overrides) in
1356 expanded if (das.id, bpr.binarypackagenameID, bpr.version)
1357 not in already_published]
1358 if not needed:
1359 return []
1360
1361 insert_head = """
1362 INSERT INTO BinaryPackagePublishingHistory
1363 (archive, distroarchseries, pocket, binarypackagerelease,
1364 component, section, priority, status, datecreated)
1365 VALUES
1366 """
1367 insert_pubs = ", ".join(
1368 "(%s)" % ", ".join(sqlvalues(
1369 get_archive(archive, bpr).id, das.id, pocket, bpr.id,
1370 get_component(archive, das.distroseries, component).id,
1371 section.id, priority, PackagePublishingStatus.PENDING,
1372 UTC_NOW))
1373 for (das, bpr, (component, section, priority)) in needed)
1374 insert_tail = " RETURNING BinaryPackagePublishingHistory.id"
1375 new_ids = IMasterStore(BinaryPackagePublishingHistory).execute(
1376 insert_head + insert_pubs + insert_tail)
1377
1378 publications = IMasterStore(BinaryPackagePublishingHistory).find(
1379 BinaryPackagePublishingHistory,
1380 BinaryPackagePublishingHistory.id.is_in(id[0] for id in new_ids))
1381 return list(publications)
1382
1383 def publishBinary(self, archive, binarypackagerelease, distroseries,
1277 component, section, priority, pocket):1384 component, section, priority, pocket):
1278 """See `IPublishingSet`."""1385 """See `IPublishingSet`."""
1279 if not binarypackagerelease.architecturespecific:1386 return self.publishBinaries(
1280 target_archs = distroarchseries.distroseries.enabled_architectures1387 archive, distroseries, pocket,
1281 else:1388 {binarypackagerelease: (component, section, priority)})
1282 target_archs = [distroarchseries]
1283
1284 # DDEBs targeted to the PRIMARY archive are published in the
1285 # corresponding DEBUG archive.
1286 if binarypackagerelease.binpackageformat == BinaryPackageFormat.DDEB:
1287 debug_archive = archive.debug_archive
1288 if debug_archive is None:
1289 raise QueueInconsistentStateError(
1290 "Could not find the corresponding DEBUG archive "
1291 "for %s" % (archive.displayname))
1292 archive = debug_archive
1293
1294 published_binaries = []
1295 for target_arch in target_archs:
1296 # We only publish the binary if it doesn't already exist in
1297 # the destination. Note that this means we don't support
1298 # override changes on their own.
1299 binaries_in_destination = archive.getAllPublishedBinaries(
1300 name=binarypackagerelease.name, exact_match=True,
1301 version=binarypackagerelease.version,
1302 status=active_publishing_status, pocket=pocket,
1303 distroarchseries=target_arch)
1304 if not bool(binaries_in_destination):
1305 published_binaries.append(
1306 getUtility(IPublishingSet).newBinaryPublication(
1307 archive, binarypackagerelease, target_arch, component,
1308 section, priority, pocket))
1309 return published_binaries
13101389
1311 def newBinaryPublication(self, archive, binarypackagerelease,1390 def newBinaryPublication(self, archive, binarypackagerelease,
1312 distroarchseries, component, section, priority,1391 distroarchseries, component, section, priority,
@@ -1318,7 +1397,7 @@
1318 archive=archive,1397 archive=archive,
1319 binarypackagerelease=binarypackagerelease,1398 binarypackagerelease=binarypackagerelease,
1320 distroarchseries=distroarchseries,1399 distroarchseries=distroarchseries,
1321 component=maybe_override_component(1400 component=get_component(
1322 archive, distroarchseries.distroseries, component),1401 archive, distroarchseries.distroseries, component),
1323 section=section,1402 section=section,
1324 priority=priority,1403 priority=priority,
@@ -1335,8 +1414,7 @@
1335 pocket=pocket,1414 pocket=pocket,
1336 archive=archive,1415 archive=archive,
1337 sourcepackagerelease=sourcepackagerelease,1416 sourcepackagerelease=sourcepackagerelease,
1338 component=maybe_override_component(1417 component=get_component(archive, distroseries, component),
1339 archive, distroseries, component),
1340 section=section,1418 section=section,
1341 status=PackagePublishingStatus.PENDING,1419 status=PackagePublishingStatus.PENDING,
1342 datecreated=UTC_NOW,1420 datecreated=UTC_NOW,
13431421
=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py 2011-02-17 17:02:54 +0000
+++ lib/lp/soyuz/model/queue.py 2011-03-07 07:05:26 +0000
@@ -1457,12 +1457,9 @@
1457 """See `IPackageUploadBuild`."""1457 """See `IPackageUploadBuild`."""
1458 # Determine the build's architecturetag1458 # Determine the build's architecturetag
1459 build_archtag = self.build.distro_arch_series.architecturetag1459 build_archtag = self.build.distro_arch_series.architecturetag
1460 # Determine the target arch series.1460 distroseries = self.packageupload.distroseries
1461 # This will raise NotFoundError if anything odd happens.
1462 target_das = self.packageupload.distroseries[build_archtag]
1463 debug(logger, "Publishing build to %s/%s/%s" % (1461 debug(logger, "Publishing build to %s/%s/%s" % (
1464 target_das.distroseries.distribution.name,1462 distroseries.distribution.name, distroseries.name,
1465 target_das.distroseries.name,
1466 build_archtag))1463 build_archtag))
14671464
1468 # First up, publish everything in this build into that dar.1465 # First up, publish everything in this build into that dar.
@@ -1478,7 +1475,7 @@
1478 getUtility(IPublishingSet).publishBinary(1475 getUtility(IPublishingSet).publishBinary(
1479 archive=self.packageupload.archive,1476 archive=self.packageupload.archive,
1480 binarypackagerelease=binary,1477 binarypackagerelease=binary,
1481 distroarchseries=target_das,1478 distroseries=distroseries,
1482 component=binary.component,1479 component=binary.component,
1483 section=binary.section,1480 section=binary.section,
1484 priority=binary.priority,1481 priority=binary.priority,
14851482
=== modified file 'lib/lp/soyuz/tests/test_publishing.py'
--- lib/lp/soyuz/tests/test_publishing.py 2011-03-03 08:01:34 +0000
+++ lib/lp/soyuz/tests/test_publishing.py 2011-03-07 07:05:26 +0000
@@ -53,6 +53,7 @@
53 PackagePublishingPriority,53 PackagePublishingPriority,
54 PackagePublishingStatus,54 PackagePublishingStatus,
55 )55 )
56from lp.soyuz.interfaces.queue import QueueInconsistentStateError
56from lp.soyuz.interfaces.section import ISectionSet57from lp.soyuz.interfaces.section import ISectionSet
57from lp.soyuz.model.processor import ProcessorFamily58from lp.soyuz.model.processor import ProcessorFamily
58from lp.soyuz.model.publishing import (59from lp.soyuz.model.publishing import (
@@ -1399,3 +1400,113 @@
1399 for bpf in files:1400 for bpf in files:
1400 bpf.libraryfile.filename1401 bpf.libraryfile.filename
1401 self.assertThat(recorder, HasQueryCount(Equals(5)))1402 self.assertThat(recorder, HasQueryCount(Equals(5)))
1403
1404
1405class TestPublishBinaries(TestCaseWithFactory):
1406 """Test PublishingSet.publishBinary() works."""
1407
1408 layer = LaunchpadZopelessLayer
1409
1410 def makeArgs(self, bprs, distroseries, archive=None):
1411 """Create a dict of arguments for publishBinary."""
1412 if archive is None:
1413 archive = distroseries.main_archive
1414 return {
1415 'archive': archive,
1416 'distroseries': distroseries,
1417 'pocket': PackagePublishingPocket.BACKPORTS,
1418 'binaries': dict(
1419 (bpr, (self.factory.makeComponent(),
1420 self.factory.makeSection(),
1421 PackagePublishingPriority.REQUIRED)) for bpr in bprs),
1422 }
1423
1424 def test_architecture_dependent(self):
1425 # Architecture-dependent binaries get created as PENDING in the
1426 # corresponding architecture of the destination series and pocket,
1427 # with the given overrides.
1428 arch_tag = self.factory.getUniqueString('arch-')
1429 orig_das = self.factory.makeDistroArchSeries(
1430 architecturetag=arch_tag)
1431 target_das = self.factory.makeDistroArchSeries(
1432 architecturetag=arch_tag)
1433 build = self.factory.makeBinaryPackageBuild(distroarchseries=orig_das)
1434 bpr = self.factory.makeBinaryPackageRelease(
1435 build=build, architecturespecific=True)
1436 args = self.makeArgs([bpr], target_das.distroseries)
1437 [bpph] = getUtility(IPublishingSet).publishBinaries(**args)
1438 overrides = args['binaries'][bpr]
1439 self.assertEqual(bpr, bpph.binarypackagerelease)
1440 self.assertEqual(
1441 (args['archive'], target_das, args['pocket']),
1442 (bpph.archive, bpph.distroarchseries, bpph.pocket))
1443 self.assertEqual(
1444 overrides, (bpph.component, bpph.section, bpph.priority))
1445 self.assertEqual(PackagePublishingStatus.PENDING, bpph.status)
1446
1447 def test_architecture_independent(self):
1448 # Architecture-independent binaries get published to all enabled
1449 # DASes in the series.
1450 bpr = self.factory.makeBinaryPackageRelease(
1451 architecturespecific=False)
1452 # Create 3 architectures. The binary will not be published in
1453 # the disabled one.
1454 target_das_a = self.factory.makeDistroArchSeries()
1455 target_das_b = self.factory.makeDistroArchSeries(
1456 distroseries=target_das_a.distroseries)
1457 target_das_c = self.factory.makeDistroArchSeries(
1458 distroseries=target_das_a.distroseries, enabled=False)
1459 args = self.makeArgs([bpr], target_das_a.distroseries)
1460 bpphs = getUtility(IPublishingSet).publishBinaries(
1461 **args)
1462 self.assertEquals(2, len(bpphs))
1463 self.assertEquals(
1464 set((target_das_a, target_das_b)),
1465 set(bpph.distroarchseries for bpph in bpphs))
1466
1467 def test_does_not_duplicate(self):
1468 # An attempt to copy something for a second time is ignored.
1469 bpr = self.factory.makeBinaryPackageRelease()
1470 target_das = self.factory.makeDistroArchSeries()
1471 args = self.makeArgs([bpr], target_das.distroseries)
1472 [new_bpph] = getUtility(IPublishingSet).publishBinaries(**args)
1473 [] = getUtility(IPublishingSet).publishBinaries(**args)
1474
1475 # But changing the target (eg. to RELEASE instead of BACKPORTS)
1476 # causes a new publication to be created.
1477 args['pocket'] = PackagePublishingPocket.RELEASE
1478 [another_bpph] = getUtility(IPublishingSet).publishBinaries(**args)
1479
1480 def test_ddebs_need_debug_archive(self):
1481 debug = self.factory.makeBinaryPackageRelease(
1482 binpackageformat=BinaryPackageFormat.DDEB)
1483 args = self.makeArgs(
1484 [debug], debug.build.distro_arch_series.distroseries)
1485 self.assertRaises(
1486 QueueInconsistentStateError,
1487 getUtility(IPublishingSet).publishBinaries, **args)
1488
1489 def test_ddebs_go_to_debug_archive(self):
1490 # Normal packages go to the given archive, but debug packages go
1491 # to the corresponding debug archive.
1492 das = self.factory.makeDistroArchSeries()
1493 self.factory.makeArchive(
1494 purpose=ArchivePurpose.DEBUG,
1495 distribution=das.distroseries.distribution)
1496 build = self.factory.makeBinaryPackageBuild(distroarchseries=das)
1497 normal = self.factory.makeBinaryPackageRelease(build=build)
1498 debug = self.factory.makeBinaryPackageRelease(
1499 build=build, binpackageformat=BinaryPackageFormat.DDEB)
1500 args = self.makeArgs([normal, debug], das.distroseries)
1501 bpphs = getUtility(IPublishingSet).publishBinaries(**args)
1502 self.assertEquals(2, len(bpphs))
1503 self.assertEquals(
1504 set((normal, debug)),
1505 set(bpph.binarypackagerelease for bpph in bpphs))
1506 self.assertEquals(
1507 set((das.main_archive, das.main_archive.debug_archive)),
1508 set(bpph.archive for bpph in bpphs))
1509
1510 # A second copy does nothing, because it checks in the debug
1511 # archive too.
1512 [] = getUtility(IPublishingSet).publishBinaries(**args)
14021513
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2011-03-03 10:58:03 +0000
+++ lib/lp/testing/factory.py 2011-03-07 07:05:26 +0000
@@ -2315,7 +2315,7 @@
2315 def makeDistroArchSeries(self, distroseries=None,2315 def makeDistroArchSeries(self, distroseries=None,
2316 architecturetag=None, processorfamily=None,2316 architecturetag=None, processorfamily=None,
2317 official=True, owner=None,2317 official=True, owner=None,
2318 supports_virtualized=False):2318 supports_virtualized=False, enabled=True):
2319 """Create a new distroarchseries"""2319 """Create a new distroarchseries"""
23202320
2321 if distroseries is None:2321 if distroseries is None:
@@ -2331,7 +2331,7 @@
2331 architecturetag = self.getUniqueString('arch')2331 architecturetag = self.getUniqueString('arch')
2332 return distroseries.newArch(2332 return distroseries.newArch(
2333 architecturetag, processorfamily, official, owner,2333 architecturetag, processorfamily, official, owner,
2334 supports_virtualized)2334 supports_virtualized, enabled)
23352335
2336 def makeComponent(self, name=None):2336 def makeComponent(self, name=None):
2337 """Make a new `IComponent`."""2337 """Make a new `IComponent`."""