Merge lp:~cjwatson/launchpad/change-override-forbid-release-stable into lp:launchpad
- change-override-forbid-release-stable
- Merge into devel
| Status: | Merged |
|---|---|
| Approved by: | William Grant on 2012-06-19 |
| Approved revision: | no longer in the source branch. |
| Merged at revision: | 15441 |
| Proposed branch: | lp:~cjwatson/launchpad/change-override-forbid-release-stable |
| Merge into: | lp:launchpad |
| Diff against target: |
665 lines (+193/-145) 15 files modified
lib/lp/archiveuploader/uploadpolicy.py (+4/-4) lib/lp/buildmaster/model/packagebuild.py (+5/-6) lib/lp/registry/doc/distroseries.txt (+26/-16) lib/lp/registry/interfaces/distroseries.py (+0/-20) lib/lp/registry/model/distroseries.py (+6/-55) lib/lp/soyuz/adapters/copypolicy.py (+1/-2) lib/lp/soyuz/doc/buildd-queuebuilder-lookup.txt (+3/-3) lib/lp/soyuz/doc/publishing.txt (+2/-0) lib/lp/soyuz/interfaces/archive.py (+22/-0) lib/lp/soyuz/model/archive.py (+33/-1) lib/lp/soyuz/model/binarypackagebuild.py (+3/-4) lib/lp/soyuz/model/publishing.py (+30/-23) lib/lp/soyuz/model/queue.py (+8/-10) lib/lp/soyuz/scripts/tests/test_changeoverride.py (+4/-0) lib/lp/soyuz/tests/test_publishing.py (+46/-1) |
| To merge this branch: | bzr merge lp:~cjwatson/launchpad/change-override-forbid-release-stable |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| William Grant | code | 2012-06-19 | Approve on 2012-06-19 |
|
Review via email:
|
|||
Commit Message
Prevent changeOverride creating publications in RELEASE pockets that will never be published.
Description of the Change
== Summary ==
Bug 530020: override changes can result in stranded publications that will never be published, since the RELEASE pockets of released DSes in the primary Ubuntu archive are immutable.
== Proposed fix ==
Move the cannotModifySuite method from the publisher down to DistroSeries so that changeOverride can use it (there are enough copies of this logic already without adding more!), and raise an exception in changeOverride if that indicates that the newly-created publication would be stranded.
== Implementation details ==
I cleaned up some useless "current = self" code in changeOverride. This made sense before the removal of secure publication records in r7659.7.1, but now it's just more typing.
== LOC Rationale ==
+42. I'm doing this so that I can land https:/
== Tests ==
bin/test -vvct test_publishing
== Demo and Q/A ==
On dogfood, attempt to run 'change-override.py -s precise -p extra base-files' and 'change-override.py -s quantal -p extra base-files'; these should respectively fail and succeed.
Preview Diff
| 1 | === modified file 'lib/lp/archiveuploader/uploadpolicy.py' |
| 2 | --- lib/lp/archiveuploader/uploadpolicy.py 2012-03-28 13:27:58 +0000 |
| 3 | +++ lib/lp/archiveuploader/uploadpolicy.py 2012-06-19 10:11:30 +0000 |
| 4 | @@ -263,10 +263,10 @@ |
| 5 | PPA uploads are always auto-approved. |
| 6 | RELEASE and PROPOSED pocket uploads (to main archives) are only |
| 7 | auto-approved if the distroseries is in a non-FROZEN state |
| 8 | - pre-release. (We already performed the |
| 9 | - IDistroSeries.canUploadToPocket check in the checkUpload base |
| 10 | - method, which will deny RELEASE uploads post-release, but it doesn't |
| 11 | - hurt to repeat this for that case.) |
| 12 | + pre-release. (We already performed the IArchive.canModifySuite |
| 13 | + check in the checkUpload base method, which will deny RELEASE |
| 14 | + uploads post-release, but it doesn't hurt to repeat this for that |
| 15 | + case.) |
| 16 | """ |
| 17 | if upload.is_ppa: |
| 18 | return True |
| 19 | |
| 20 | === modified file 'lib/lp/buildmaster/model/packagebuild.py' |
| 21 | --- lib/lp/buildmaster/model/packagebuild.py 2012-01-11 08:52:22 +0000 |
| 22 | +++ lib/lp/buildmaster/model/packagebuild.py 2012-06-19 10:11:30 +0000 |
| 23 | @@ -1,4 +1,4 @@ |
| 24 | -# Copyright 2010 Canonical Ltd. This software is licensed under the |
| 25 | +# Copyright 2010-2012 Canonical Ltd. This software is licensed under the |
| 26 | # GNU Affero General Public License version 3 (see the file LICENSE). |
| 27 | |
| 28 | __metaclass__ = type |
| 29 | @@ -330,11 +330,10 @@ |
| 30 | return self._release_builder_and_remove_queue_item() |
| 31 | |
| 32 | # Explode before collect a binary that is denied in this |
| 33 | - # distroseries/pocket |
| 34 | - if not self.archive.allowUpdatesToReleasePocket(): |
| 35 | - assert self.distro_series.canUploadToPocket(self.pocket), ( |
| 36 | - "%s (%s) can not be built for pocket %s: illegal status" |
| 37 | - % (self.title, self.id, self.pocket.name)) |
| 38 | + # distroseries/pocket/archive |
| 39 | + assert self.archive.canModifySuite(self.distro_series, self.pocket), ( |
| 40 | + "%s (%s) can not be built for pocket %s in %s: illegal status" |
| 41 | + % (self.title, self.id, self.pocket.name, self.archive)) |
| 42 | |
| 43 | # Ensure we have the correct build root as: |
| 44 | # <BUILDMASTER_ROOT>/incoming/<UPLOAD_LEAF>/<TARGET_PATH>/[FILES] |
| 45 | |
| 46 | === modified file 'lib/lp/registry/doc/distroseries.txt' |
| 47 | --- lib/lp/registry/doc/distroseries.txt 2012-04-23 22:18:46 +0000 |
| 48 | +++ lib/lp/registry/doc/distroseries.txt 2012-06-19 10:11:30 +0000 |
| 49 | @@ -166,10 +166,11 @@ |
| 50 | |
| 51 | See distroseries-publishing-lookups.txt for more information. |
| 52 | |
| 53 | -canUploadToPocket method helps us to decide if an upload is allowed or |
| 54 | -not, according to the distroseries status and the upload target pocket. |
| 55 | +canModifySuite method helps us to decide if an upload is allowed or not, |
| 56 | +according to the distroseries status and the upload target pocket. |
| 57 | |
| 58 | >>> ubuntu = getUtility(IDistributionSet)['ubuntu'] |
| 59 | + >>> archive = ubuntu.main_archive |
| 60 | >>> breezy_autotest = ubuntu['breezy-autotest'] |
| 61 | >>> hoary = ubuntu['hoary'] |
| 62 | |
| 63 | @@ -178,16 +179,18 @@ |
| 64 | |
| 65 | >>> warty.status.name |
| 66 | 'CURRENT' |
| 67 | - >>> warty.canUploadToPocket(PackagePublishingPocket.RELEASE) |
| 68 | + >>> archive.canModifySuite(warty, PackagePublishingPocket.RELEASE) |
| 69 | False |
| 70 | - >>> warty.canUploadToPocket(PackagePublishingPocket.SECURITY) |
| 71 | + >>> archive.canModifySuite(warty, PackagePublishingPocket.SECURITY) |
| 72 | True |
| 73 | |
| 74 | >>> breezy_autotest.status.name |
| 75 | 'EXPERIMENTAL' |
| 76 | - >>> breezy_autotest.canUploadToPocket(PackagePublishingPocket.RELEASE) |
| 77 | + >>> archive.canModifySuite( |
| 78 | + ... breezy_autotest, PackagePublishingPocket.RELEASE) |
| 79 | True |
| 80 | - >>> breezy_autotest.canUploadToPocket(PackagePublishingPocket.SECURITY) |
| 81 | + >>> archive.canModifySuite( |
| 82 | + ... breezy_autotest, PackagePublishingPocket.SECURITY) |
| 83 | False |
| 84 | |
| 85 | The FROZEN status is special. Uploads are allowed for all pockets as |
| 86 | @@ -198,20 +201,21 @@ |
| 87 | |
| 88 | >>> hoary.status.name |
| 89 | 'FROZEN' |
| 90 | - >>> hoary.canUploadToPocket(PackagePublishingPocket.RELEASE) |
| 91 | + >>> archive.canModifySuite(hoary, PackagePublishingPocket.RELEASE) |
| 92 | True |
| 93 | - >>> hoary.canUploadToPocket(PackagePublishingPocket.SECURITY) |
| 94 | + >>> archive.canModifySuite(hoary, PackagePublishingPocket.SECURITY) |
| 95 | True |
| 96 | |
| 97 | The PROPOSED pocket is also special. Pre-release, it may be used for |
| 98 | staging uploads on their way into the RELEASE pocket; post-release, it may |
| 99 | be used for staging uploads on their way into the UPDATES pocket. |
| 100 | |
| 101 | - >>> warty.canUploadToPocket(PackagePublishingPocket.PROPOSED) |
| 102 | - True |
| 103 | - >>> breezy_autotest.canUploadToPocket(PackagePublishingPocket.PROPOSED) |
| 104 | - True |
| 105 | - >>> hoary.canUploadToPocket(PackagePublishingPocket.PROPOSED) |
| 106 | + >>> archive.canModifySuite(warty, PackagePublishingPocket.PROPOSED) |
| 107 | + True |
| 108 | + >>> archive.canModifySuite( |
| 109 | + ... breezy_autotest, PackagePublishingPocket.PROPOSED) |
| 110 | + True |
| 111 | + >>> archive.canModifySuite(hoary, PackagePublishingPocket.PROPOSED) |
| 112 | True |
| 113 | |
| 114 | Package searching |
| 115 | @@ -517,8 +521,12 @@ |
| 116 | ------------------------------------------------ |
| 117 | |
| 118 | >>> from lp.registry.interfaces.sourcepackage import ISourcePackage |
| 119 | - >>> from lp.soyuz.interfaces.distroseriesbinarypackage import IDistroSeriesBinaryPackage |
| 120 | - >>> from lp.soyuz.interfaces.distroseriessourcepackagerelease import IDistroSeriesSourcePackageRelease |
| 121 | + >>> from lp.soyuz.interfaces.distroseriesbinarypackage import ( |
| 122 | + ... IDistroSeriesBinaryPackage, |
| 123 | + ... ) |
| 124 | + >>> from lp.soyuz.interfaces.distroseriessourcepackagerelease import ( |
| 125 | + ... IDistroSeriesSourcePackageRelease, |
| 126 | + ... ) |
| 127 | |
| 128 | >>> pmount_src_name = SourcePackageName.byName('pmount') |
| 129 | >>> pmount_source = hoary.getSourcePackage(pmount_src_name) |
| 130 | @@ -722,7 +730,9 @@ |
| 131 | 4 |
| 132 | >>> warty_mozilla_pub_bin = warty_mozilla_pub_binaries[0] |
| 133 | |
| 134 | - >>> from lp.soyuz.interfaces.publishing import IBinaryPackagePublishingHistory |
| 135 | + >>> from lp.soyuz.interfaces.publishing import ( |
| 136 | + ... IBinaryPackagePublishingHistory, |
| 137 | + ... ) |
| 138 | >>> verifyObject(IBinaryPackagePublishingHistory, warty_mozilla_pub_bin) |
| 139 | True |
| 140 | |
| 141 | |
| 142 | === modified file 'lib/lp/registry/interfaces/distroseries.py' |
| 143 | --- lib/lp/registry/interfaces/distroseries.py 2012-01-10 09:55:24 +0000 |
| 144 | +++ lib/lp/registry/interfaces/distroseries.py 2012-06-19 10:11:30 +0000 |
| 145 | @@ -402,26 +402,6 @@ |
| 146 | development moves on to the other pockets. |
| 147 | """ |
| 148 | |
| 149 | - def canUploadToPocket(pocket): |
| 150 | - """Decides whether or not allow uploads for a given pocket. |
| 151 | - |
| 152 | - Only allow uploads for RELEASE pocket in unreleased |
| 153 | - distroseries and the opposite, only allow uploads for |
| 154 | - non-RELEASE pockets in released distroseries. |
| 155 | - For instance, in edgy time : |
| 156 | - |
| 157 | - warty -> DENY |
| 158 | - edgy -> ALLOW |
| 159 | - warty-updates -> ALLOW |
| 160 | - edgy-security -> DENY |
| 161 | - |
| 162 | - Note that FROZEN is not considered either 'stable' or 'unstable' |
| 163 | - state. Uploads to a FROZEN distroseries will end up in the |
| 164 | - UNAPPROVED queue. |
| 165 | - |
| 166 | - Return True if the upload is allowed and False if denied. |
| 167 | - """ |
| 168 | - |
| 169 | def getLatestUploads(): |
| 170 | """Return the latest five source uploads for this DistroSeries. |
| 171 | |
| 172 | |
| 173 | === modified file 'lib/lp/registry/model/distroseries.py' |
| 174 | --- lib/lp/registry/model/distroseries.py 2012-05-14 03:07:32 +0000 |
| 175 | +++ lib/lp/registry/model/distroseries.py 2012-06-19 10:11:30 +0000 |
| 176 | @@ -709,33 +709,6 @@ |
| 177 | """See `HasMilestonesMixin`.""" |
| 178 | return (Milestone.distroseries == self) |
| 179 | |
| 180 | - def canUploadToPocket(self, pocket): |
| 181 | - """See `IDistroSeries`.""" |
| 182 | - # Allow everything for distroseries in FROZEN state. |
| 183 | - if self.status == SeriesStatus.FROZEN: |
| 184 | - return True |
| 185 | - |
| 186 | - # Define stable/released states. |
| 187 | - stable_states = (SeriesStatus.SUPPORTED, |
| 188 | - SeriesStatus.CURRENT) |
| 189 | - |
| 190 | - # Deny uploads for RELEASE pocket in stable states. |
| 191 | - if (pocket == PackagePublishingPocket.RELEASE and |
| 192 | - self.status in stable_states): |
| 193 | - return False |
| 194 | - |
| 195 | - # Deny uploads for post-release-only pockets in unstable states. |
| 196 | - pre_release_pockets = ( |
| 197 | - PackagePublishingPocket.RELEASE, |
| 198 | - PackagePublishingPocket.PROPOSED, |
| 199 | - ) |
| 200 | - if (pocket not in pre_release_pockets and |
| 201 | - self.status not in stable_states): |
| 202 | - return False |
| 203 | - |
| 204 | - # Allow anything else. |
| 205 | - return True |
| 206 | - |
| 207 | def updatePackageCount(self): |
| 208 | """See `IDistroSeries`.""" |
| 209 | self.sourcecount = IStore(SourcePackagePublishingHistory).find( |
| 210 | @@ -1610,34 +1583,12 @@ |
| 211 | if is_careful: |
| 212 | return True |
| 213 | |
| 214 | - # PPA and PARTNER allow everything. |
| 215 | - if publication.archive.allowUpdatesToReleasePocket(): |
| 216 | - return True |
| 217 | - |
| 218 | - # FROZEN state also allow all pockets to be published. |
| 219 | - if self.status == SeriesStatus.FROZEN: |
| 220 | - return True |
| 221 | - |
| 222 | - # If we're not republishing, we want to make sure that |
| 223 | - # we're not publishing packages into the wrong pocket. |
| 224 | - # Unfortunately for careful mode that can't hold true |
| 225 | - # because we indeed need to republish everything. |
| 226 | - pre_release_pockets = ( |
| 227 | - PackagePublishingPocket.RELEASE, |
| 228 | - PackagePublishingPocket.PROPOSED, |
| 229 | - ) |
| 230 | - if self.isUnstable() and publication.pocket not in pre_release_pockets: |
| 231 | - log.error("Tried to publish %s (%s) into a non-release " |
| 232 | - "pocket on unstable series %s, skipping" |
| 233 | - % (publication.displayname, publication.id, |
| 234 | - self.displayname)) |
| 235 | - return False |
| 236 | - if (not self.isUnstable() and |
| 237 | - publication.pocket == PackagePublishingPocket.RELEASE): |
| 238 | - log.error("Tried to publish %s (%s) into release pocket " |
| 239 | - "on stable series %s, skipping" |
| 240 | - % (publication.displayname, publication.id, |
| 241 | - self.displayname)) |
| 242 | + if not publication.archive.canModifySuite(self, publication.pocket): |
| 243 | + log.error( |
| 244 | + "Tried to publish %s (%s) into the %s pocket on series %s " |
| 245 | + "(%s), skipping" % ( |
| 246 | + publication.displayname, publication.id, |
| 247 | + publication.pocket, self.displayname, self.status.name)) |
| 248 | return False |
| 249 | |
| 250 | return True |
| 251 | |
| 252 | === modified file 'lib/lp/soyuz/adapters/copypolicy.py' |
| 253 | --- lib/lp/soyuz/adapters/copypolicy.py 2012-03-28 13:27:58 +0000 |
| 254 | +++ lib/lp/soyuz/adapters/copypolicy.py 2012-06-19 10:11:30 +0000 |
| 255 | @@ -45,8 +45,7 @@ |
| 256 | # If the pocket is RELEASE or PROPOSED and we're not frozen then you |
| 257 | # can upload to it. Any other states mean the upload is unapproved. |
| 258 | # |
| 259 | - # This check is orthogonal to the |
| 260 | - # IDistroSeries.canUploadToPocket check. |
| 261 | + # This check is orthogonal to the IArchive.canModifySuite check. |
| 262 | auto_approve_pockets = ( |
| 263 | PackagePublishingPocket.RELEASE, |
| 264 | PackagePublishingPocket.PROPOSED, |
| 265 | |
| 266 | === modified file 'lib/lp/soyuz/doc/buildd-queuebuilder-lookup.txt' |
| 267 | --- lib/lp/soyuz/doc/buildd-queuebuilder-lookup.txt 2011-12-30 06:14:56 +0000 |
| 268 | +++ lib/lp/soyuz/doc/buildd-queuebuilder-lookup.txt 2012-06-19 10:11:30 +0000 |
| 269 | @@ -174,9 +174,9 @@ |
| 270 | |
| 271 | Note that, also the publications targeted to post-release pockets are |
| 272 | returned, but they won't be dispatched until they can be accepted (see |
| 273 | -IDistroSeries.canUploadToPocket). This nuance will be more explored |
| 274 | -when fixing #67790 when we will start publishing and building |
| 275 | -post-release pocket in FROZEN state. |
| 276 | +IArchive.canModifySuite). This nuance will be more explored when fixing |
| 277 | +#67790 when we will start publishing and building post-release pocket in |
| 278 | +FROZEN state. |
| 279 | |
| 280 | Summing up, all the 8 test publications will be returned from the lookup: |
| 281 | |
| 282 | |
| 283 | === modified file 'lib/lp/soyuz/doc/publishing.txt' |
| 284 | --- lib/lp/soyuz/doc/publishing.txt 2011-12-30 06:14:56 +0000 |
| 285 | +++ lib/lp/soyuz/doc/publishing.txt 2012-06-19 10:11:30 +0000 |
| 286 | @@ -475,7 +475,9 @@ |
| 287 | |
| 288 | 'distroseries' and 'archive' will be constant. |
| 289 | |
| 290 | + >>> from lp.registry.interfaces.series import SeriesStatus |
| 291 | >>> distroseries = source.distroseries |
| 292 | + >>> distroseries.status = SeriesStatus.CURRENT |
| 293 | >>> archive = source.archive |
| 294 | |
| 295 | 'pocket' will be UPDATES. |
| 296 | |
| 297 | === modified file 'lib/lp/soyuz/interfaces/archive.py' |
| 298 | --- lib/lp/soyuz/interfaces/archive.py 2012-06-12 04:05:44 +0000 |
| 299 | +++ lib/lp/soyuz/interfaces/archive.py 2012-06-19 10:11:30 +0000 |
| 300 | @@ -576,6 +576,28 @@ |
| 301 | :return: True if they can, False if they cannot. |
| 302 | """ |
| 303 | |
| 304 | + def canModifySuite(distroseries, pocket): |
| 305 | + """Decides whether or not to allow uploads for a given DS/pocket. |
| 306 | + |
| 307 | + Some archive types (e.g. PPAs) allow uploads to the RELEASE pocket |
| 308 | + regardless of the distroseries state. For others (principally |
| 309 | + primary archives), only allow uploads for RELEASE pocket in |
| 310 | + unreleased distroseries, and conversely only allow uploads for |
| 311 | + non-RELEASE pockets in released distroseries. |
| 312 | + For instance, in edgy time : |
| 313 | + |
| 314 | + warty -> DENY |
| 315 | + edgy -> ALLOW |
| 316 | + warty-updates -> ALLOW |
| 317 | + edgy-security -> DENY |
| 318 | + |
| 319 | + Note that FROZEN is not considered either 'stable' or 'unstable' |
| 320 | + state. Uploads to a FROZEN distroseries will end up in the |
| 321 | + UNAPPROVED queue. |
| 322 | + |
| 323 | + Return True if the upload is allowed and False if denied. |
| 324 | + """ |
| 325 | + |
| 326 | def checkUploadToPocket(distroseries, pocket): |
| 327 | """Check if an upload to a particular archive and pocket is possible. |
| 328 | |
| 329 | |
| 330 | === modified file 'lib/lp/soyuz/model/archive.py' |
| 331 | --- lib/lp/soyuz/model/archive.py 2012-06-15 10:21:34 +0000 |
| 332 | +++ lib/lp/soyuz/model/archive.py 2012-06-19 10:11:30 +0000 |
| 333 | @@ -67,6 +67,7 @@ |
| 334 | ) |
| 335 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
| 336 | from lp.registry.interfaces.role import IHasOwner |
| 337 | +from lp.registry.interfaces.series import SeriesStatus |
| 338 | from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet |
| 339 | from lp.registry.model.sourcepackagename import SourcePackageName |
| 340 | from lp.registry.model.teammembership import TeamParticipation |
| 341 | @@ -1227,6 +1228,37 @@ |
| 342 | strict_component=True) |
| 343 | return reason is None |
| 344 | |
| 345 | + def canModifySuite(self, distroseries, pocket): |
| 346 | + """See `IArchive`.""" |
| 347 | + # PPA and PARTNER allow everything. |
| 348 | + if self.allowUpdatesToReleasePocket(): |
| 349 | + return True |
| 350 | + |
| 351 | + # Allow everything for distroseries in FROZEN state. |
| 352 | + if distroseries.status == SeriesStatus.FROZEN: |
| 353 | + return True |
| 354 | + |
| 355 | + # Define stable/released states. |
| 356 | + stable_states = (SeriesStatus.SUPPORTED, |
| 357 | + SeriesStatus.CURRENT) |
| 358 | + |
| 359 | + # Deny uploads for RELEASE pocket in stable states. |
| 360 | + if (pocket == PackagePublishingPocket.RELEASE and |
| 361 | + distroseries.status in stable_states): |
| 362 | + return False |
| 363 | + |
| 364 | + # Deny uploads for post-release-only pockets in unstable states. |
| 365 | + pre_release_pockets = ( |
| 366 | + PackagePublishingPocket.RELEASE, |
| 367 | + PackagePublishingPocket.PROPOSED, |
| 368 | + ) |
| 369 | + if (pocket not in pre_release_pockets and |
| 370 | + distroseries.status not in stable_states): |
| 371 | + return False |
| 372 | + |
| 373 | + # Allow anything else. |
| 374 | + return True |
| 375 | + |
| 376 | def checkUploadToPocket(self, distroseries, pocket): |
| 377 | """See `IArchive`.""" |
| 378 | if self.is_partner: |
| 379 | @@ -1247,7 +1279,7 @@ |
| 380 | # state. |
| 381 | # XXX julian 2005-05-29 bug=117557: |
| 382 | # This is a greasy hack until bug #117557 is fixed. |
| 383 | - if not distroseries.canUploadToPocket(pocket): |
| 384 | + if not self.canModifySuite(distroseries, pocket): |
| 385 | return CannotUploadToPocket(distroseries, pocket) |
| 386 | |
| 387 | def _checkUpload(self, person, distroseries, sourcepackagename, component, |
| 388 | |
| 389 | === modified file 'lib/lp/soyuz/model/binarypackagebuild.py' |
| 390 | --- lib/lp/soyuz/model/binarypackagebuild.py 2012-02-13 04:20:08 +0000 |
| 391 | +++ lib/lp/soyuz/model/binarypackagebuild.py 2012-06-19 10:11:30 +0000 |
| 392 | @@ -1,4 +1,4 @@ |
| 393 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
| 394 | +# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
| 395 | # GNU Affero General Public License version 3 (see the file LICENSE). |
| 396 | |
| 397 | # pylint: disable-msg=E0611,W0212 |
| 398 | @@ -327,9 +327,8 @@ |
| 399 | def can_be_retried(self): |
| 400 | """See `IBuild`.""" |
| 401 | # First check that the slave scanner would pick up the build record |
| 402 | - # if we reset it. PPA and Partner builds are always ok. |
| 403 | - if (self.archive.purpose == ArchivePurpose.PRIMARY and |
| 404 | - not self.distro_series.canUploadToPocket(self.pocket)): |
| 405 | + # if we reset it. |
| 406 | + if not self.archive.canModifySuite(self.distro_series, self.pocket): |
| 407 | # The slave scanner would not pick this up, so it cannot be |
| 408 | # re-tried. |
| 409 | return False |
| 410 | |
| 411 | === modified file 'lib/lp/soyuz/model/publishing.py' |
| 412 | --- lib/lp/soyuz/model/publishing.py 2012-05-21 07:34:15 +0000 |
| 413 | +++ lib/lp/soyuz/model/publishing.py 2012-06-19 10:11:30 +0000 |
| 414 | @@ -787,17 +787,13 @@ |
| 415 | raise AssertionError("changeOverride must be passed either a" |
| 416 | " new component or new section") |
| 417 | |
| 418 | - # Retrieve current publishing info |
| 419 | - current = self |
| 420 | - |
| 421 | # Check there is a change to make |
| 422 | if new_component is None: |
| 423 | - new_component = current.component |
| 424 | + new_component = self.component |
| 425 | if new_section is None: |
| 426 | - new_section = current.section |
| 427 | + new_section = self.section |
| 428 | |
| 429 | - if (new_component == current.component and |
| 430 | - new_section == current.section): |
| 431 | + if new_component == self.component and new_section == self.section: |
| 432 | return |
| 433 | |
| 434 | # See if the archive has changed by virtue of the component |
| 435 | @@ -805,18 +801,25 @@ |
| 436 | distribution = self.distroseries.distribution |
| 437 | new_archive = distribution.getArchiveByComponent( |
| 438 | new_component.name) |
| 439 | - if new_archive != None and new_archive != current.archive: |
| 440 | + if new_archive != None and new_archive != self.archive: |
| 441 | raise ArchiveOverriderError( |
| 442 | "Overriding component to '%s' failed because it would " |
| 443 | "require a new archive." % new_component.name) |
| 444 | |
| 445 | + # Refuse to create new publication records that will never be |
| 446 | + # published. |
| 447 | + if not self.archive.canModifySuite(self.distroseries, self.pocket): |
| 448 | + raise ArchiveOverriderError( |
| 449 | + "Cannot change overrides in suite '%s'" % |
| 450 | + self.distroseries.getSuite(self.pocket)) |
| 451 | + |
| 452 | return getUtility(IPublishingSet).newSourcePublication( |
| 453 | - distroseries=current.distroseries, |
| 454 | - sourcepackagerelease=current.sourcepackagerelease, |
| 455 | - pocket=current.pocket, |
| 456 | + distroseries=self.distroseries, |
| 457 | + sourcepackagerelease=self.sourcepackagerelease, |
| 458 | + pocket=self.pocket, |
| 459 | component=new_component, |
| 460 | section=new_section, |
| 461 | - archive=current.archive) |
| 462 | + archive=self.archive) |
| 463 | |
| 464 | def copyTo(self, distroseries, pocket, archive, override=None, |
| 465 | create_dsd_job=True, creator=None, sponsor=None, |
| 466 | @@ -1202,20 +1205,17 @@ |
| 467 | raise AssertionError("changeOverride must be passed a new" |
| 468 | "component, section and/or priority.") |
| 469 | |
| 470 | - # Retrieve current publishing info |
| 471 | - current = self |
| 472 | - |
| 473 | # Check there is a change to make |
| 474 | if new_component is None: |
| 475 | - new_component = current.component |
| 476 | + new_component = self.component |
| 477 | if new_section is None: |
| 478 | - new_section = current.section |
| 479 | + new_section = self.section |
| 480 | if new_priority is None: |
| 481 | - new_priority = current.priority |
| 482 | + new_priority = self.priority |
| 483 | |
| 484 | - if (new_component == current.component and |
| 485 | - new_section == current.section and |
| 486 | - new_priority == current.priority): |
| 487 | + if (new_component == self.component and |
| 488 | + new_section == self.section and |
| 489 | + new_priority == self.priority): |
| 490 | return |
| 491 | |
| 492 | # See if the archive has changed by virtue of the component changing: |
| 493 | @@ -1227,6 +1227,13 @@ |
| 494 | "Overriding component to '%s' failed because it would " |
| 495 | "require a new archive." % new_component.name) |
| 496 | |
| 497 | + # Refuse to create new publication records that will never be |
| 498 | + # published. |
| 499 | + if not self.archive.canModifySuite(self.distroseries, self.pocket): |
| 500 | + raise ArchiveOverriderError( |
| 501 | + "Cannot change overrides in suite '%s'" % |
| 502 | + self.distroseries.getSuite(self.pocket)) |
| 503 | + |
| 504 | # Append the modified package publishing entry |
| 505 | return BinaryPackagePublishingHistory( |
| 506 | binarypackagename=self.binarypackagerelease.binarypackagename, |
| 507 | @@ -1234,11 +1241,11 @@ |
| 508 | distroarchseries=self.distroarchseries, |
| 509 | status=PackagePublishingStatus.PENDING, |
| 510 | datecreated=UTC_NOW, |
| 511 | - pocket=current.pocket, |
| 512 | + pocket=self.pocket, |
| 513 | component=new_component, |
| 514 | section=new_section, |
| 515 | priority=new_priority, |
| 516 | - archive=current.archive) |
| 517 | + archive=self.archive) |
| 518 | |
| 519 | def copyTo(self, distroseries, pocket, archive): |
| 520 | """See `BinaryPackagePublishingHistory`.""" |
| 521 | |
| 522 | === modified file 'lib/lp/soyuz/model/queue.py' |
| 523 | --- lib/lp/soyuz/model/queue.py 2012-05-25 15:31:50 +0000 |
| 524 | +++ lib/lp/soyuz/model/queue.py 2012-06-19 10:11:30 +0000 |
| 525 | @@ -277,11 +277,10 @@ |
| 526 | """See `IPackageUpload`.""" |
| 527 | # Explode if something wrong like warty/RELEASE pass through |
| 528 | # NascentUpload/UploadPolicies checks for 'ubuntu' main distro. |
| 529 | - if not self.archive.allowUpdatesToReleasePocket(): |
| 530 | - assert self.distroseries.canUploadToPocket(self.pocket), ( |
| 531 | - "Not permitted acceptance in the %s pocket in a " |
| 532 | - "series in the '%s' state." % ( |
| 533 | - self.pocket.name, self.distroseries.status.name)) |
| 534 | + assert self.archive.canModifySuite(self.distroseries, self.pocket), ( |
| 535 | + "Not permitted acceptance in the %s pocket in a " |
| 536 | + "series in the '%s' state." % ( |
| 537 | + self.pocket.name, self.distroseries.status.name)) |
| 538 | |
| 539 | if self.status == PackageUploadStatus.ACCEPTED: |
| 540 | raise QueueInconsistentStateError( |
| 541 | @@ -738,11 +737,10 @@ |
| 542 | "Can not publish a non-ACCEPTED queue record (%s)" % self.id) |
| 543 | # Explode if something wrong like warty/RELEASE pass through |
| 544 | # NascentUpload/UploadPolicies checks |
| 545 | - if not self.archive.allowUpdatesToReleasePocket(): |
| 546 | - assert self.distroseries.canUploadToPocket(self.pocket), ( |
| 547 | - "Not permitted to publish to the %s pocket in a " |
| 548 | - "series in the '%s' state." % ( |
| 549 | - self.pocket.name, self.distroseries.status.name)) |
| 550 | + assert self.archive.canModifySuite(self.distroseries, self.pocket), ( |
| 551 | + "Not permitted to publish to the %s pocket in a " |
| 552 | + "series in the '%s' state." % ( |
| 553 | + self.pocket.name, self.distroseries.status.name)) |
| 554 | |
| 555 | publishing_records = [] |
| 556 | # In realising an upload we first load all the sources into |
| 557 | |
| 558 | === modified file 'lib/lp/soyuz/scripts/tests/test_changeoverride.py' |
| 559 | --- lib/lp/soyuz/scripts/tests/test_changeoverride.py 2012-01-01 02:58:52 +0000 |
| 560 | +++ lib/lp/soyuz/scripts/tests/test_changeoverride.py 2012-06-19 10:11:30 +0000 |
| 561 | @@ -12,6 +12,7 @@ |
| 562 | from lp.registry.interfaces.distribution import IDistributionSet |
| 563 | from lp.registry.interfaces.person import IPersonSet |
| 564 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
| 565 | +from lp.registry.interfaces.series import SeriesStatus |
| 566 | from lp.services.librarian.interfaces import ILibraryFileAliasSet |
| 567 | from lp.services.log.logger import BufferLogger |
| 568 | from lp.soyuz.enums import PackagePublishingPriority |
| 569 | @@ -263,6 +264,7 @@ |
| 570 | This test checks the expected behaviour for each of them. |
| 571 | """ |
| 572 | self._setupOverridePublishingContext() |
| 573 | + self.warty.status = SeriesStatus.DEVELOPMENT |
| 574 | |
| 575 | changer = self.getChanger( |
| 576 | component="universe", section="web", priority='extra') |
| 577 | @@ -364,6 +366,7 @@ |
| 578 | This behaviour is inherited from `SoyuzScript`. |
| 579 | """ |
| 580 | self._setupOverridePublishingContext() |
| 581 | + self.warty.status = SeriesStatus.DEVELOPMENT |
| 582 | changer = self.getChanger( |
| 583 | component="universe", section="web", priority='extra', |
| 584 | package_version='0.9') |
| 585 | @@ -398,6 +401,7 @@ |
| 586 | This behaviour is inherited from `SoyuzScript`. |
| 587 | """ |
| 588 | self._setupOverridePublishingContext() |
| 589 | + self.warty.status = SeriesStatus.DEVELOPMENT |
| 590 | changer = self.getChanger( |
| 591 | component="universe", section="web", priority='extra', |
| 592 | arch_tag='i386') |
| 593 | |
| 594 | === modified file 'lib/lp/soyuz/tests/test_publishing.py' |
| 595 | --- lib/lp/soyuz/tests/test_publishing.py 2012-01-20 15:42:44 +0000 |
| 596 | +++ lib/lp/soyuz/tests/test_publishing.py 2012-06-19 10:11:30 +0000 |
| 597 | @@ -1,4 +1,4 @@ |
| 598 | -# Copyright 2009-2011 Canonical Ltd. This software is licensed under the |
| 599 | +# Copyright 2009-2012 Canonical Ltd. This software is licensed under the |
| 600 | # GNU Affero General Public License version 3 (see the file LICENSE). |
| 601 | |
| 602 | """Test native publication workflow for Soyuz. """ |
| 603 | @@ -24,6 +24,7 @@ |
| 604 | from lp.registry.interfaces.distribution import IDistributionSet |
| 605 | from lp.registry.interfaces.person import IPersonSet |
| 606 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
| 607 | +from lp.registry.interfaces.series import SeriesStatus |
| 608 | from lp.registry.interfaces.sourcepackage import SourcePackageUrgency |
| 609 | from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet |
| 610 | from lp.services.config import config |
| 611 | @@ -58,6 +59,7 @@ |
| 612 | BinaryPackagePublishingHistory, |
| 613 | SourcePackagePublishingHistory, |
| 614 | ) |
| 615 | +from lp.soyuz.scripts.changeoverride import ArchiveOverriderError |
| 616 | from lp.testing import ( |
| 617 | StormStatementRecorder, |
| 618 | TestCaseWithFactory, |
| 619 | @@ -1645,3 +1647,46 @@ |
| 620 | # archive too. |
| 621 | self.assertContentEqual( |
| 622 | [], getUtility(IPublishingSet).publishBinaries(**args)) |
| 623 | + |
| 624 | + |
| 625 | +class TestChangeOverride(TestNativePublishingBase): |
| 626 | + """Test that changing overrides works.""" |
| 627 | + |
| 628 | + def setUpOverride(self, status, pocket=PackagePublishingPocket.RELEASE, |
| 629 | + binary=False): |
| 630 | + self.distroseries.status = status |
| 631 | + if binary: |
| 632 | + pub = self.getPubBinaries(pocket=pocket)[0] |
| 633 | + else: |
| 634 | + pub = self.getPubSource(pocket=pocket) |
| 635 | + universe = getUtility(IComponentSet)["universe"] |
| 636 | + return pub.changeOverride(new_component=universe) |
| 637 | + |
| 638 | + def assertCanOverride(self, *args, **kwargs): |
| 639 | + new_pub = self.setUpOverride(*args, **kwargs) |
| 640 | + self.assertEqual("universe", new_pub.component.name) |
| 641 | + |
| 642 | + def assertCannotOverride(self, *args, **kwargs): |
| 643 | + self.assertRaises( |
| 644 | + ArchiveOverriderError, self.setUpOverride, *args, **kwargs) |
| 645 | + |
| 646 | + def test_changeOverride_forbids_stable_RELEASE(self): |
| 647 | + # changeOverride is not allowed in the RELEASE pocket of a stable |
| 648 | + # distroseries. |
| 649 | + self.assertCannotOverride(SeriesStatus.CURRENT) |
| 650 | + self.assertCannotOverride(SeriesStatus.CURRENT, binary=True) |
| 651 | + |
| 652 | + def test_changeOverride_allows_development_RELEASE(self): |
| 653 | + # changeOverride is allowed in the RELEASE pocket of a development |
| 654 | + # distroseries. |
| 655 | + self.assertCanOverride(SeriesStatus.DEVELOPMENT) |
| 656 | + self.assertCanOverride(SeriesStatus.DEVELOPMENT, binary=True) |
| 657 | + |
| 658 | + def test_changeOverride_allows_stable_PROPOSED(self): |
| 659 | + # changeOverride is allowed in the PROPOSED pocket of a stable |
| 660 | + # distroseries. |
| 661 | + self.assertCanOverride( |
| 662 | + SeriesStatus.CURRENT, pocket=PackagePublishingPocket.PROPOSED) |
| 663 | + self.assertCanOverride( |
| 664 | + SeriesStatus.CURRENT, pocket=PackagePublishingPocket.PROPOSED, |
| 665 | + binary=True) |
