Merge lp:~julian-edwards/launchpad/arch-all-domination-bug-34086 into lp:launchpad
- arch-all-domination-bug-34086
- Merge into devel
Proposed by
Julian Edwards
Status: | Merged |
---|---|
Approved by: | William Grant |
Approved revision: | no longer in the source branch. |
Merged at revision: | 14169 |
Proposed branch: | lp:~julian-edwards/launchpad/arch-all-domination-bug-34086 |
Merge into: | lp:launchpad |
Diff against target: |
528 lines (+346/-60) 4 files modified
lib/lp/archivepublisher/domination.py (+52/-30) lib/lp/archivepublisher/tests/test_dominator.py (+133/-30) lib/lp/soyuz/model/publishing.py (+55/-0) lib/lp/soyuz/tests/test_publishing.py (+106/-0) |
To merge this branch: | bzr merge lp:~julian-edwards/launchpad/arch-all-domination-bug-34086 |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant (community) | code | Approve | |
Review via email: mp+79675@code.launchpad.net |
Commit message
[r=wgrant][bug=34086] Prevent superseding of arch-indep binaries until all binaries from the same source are all also superseded.
Description of the change
Fix problems discovered in the previous branch that was backed out where arch-indep and arch-specific binaries flip.
Since the last branch is being re-applied the diff is large. The actual changes are here: http://
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/archivepublisher/domination.py' | |||
2 | --- lib/lp/archivepublisher/domination.py 2011-10-18 02:09:38 +0000 | |||
3 | +++ lib/lp/archivepublisher/domination.py 2011-10-18 12:00:30 +0000 | |||
4 | @@ -153,6 +153,7 @@ | |||
5 | 153 | class. | 153 | class. |
6 | 154 | """ | 154 | """ |
7 | 155 | def __init__(self, is_source=True): | 155 | def __init__(self, is_source=True): |
8 | 156 | self.is_source = is_source | ||
9 | 156 | if is_source: | 157 | if is_source: |
10 | 157 | self.traits = SourcePublicationTraits | 158 | self.traits = SourcePublicationTraits |
11 | 158 | else: | 159 | else: |
12 | @@ -204,6 +205,27 @@ | |||
13 | 204 | self.logger = logger | 205 | self.logger = logger |
14 | 205 | self.archive = archive | 206 | self.archive = archive |
15 | 206 | 207 | ||
16 | 208 | def _checkArchIndep(self, publication): | ||
17 | 209 | """Return True if the binary publication can be superseded. | ||
18 | 210 | |||
19 | 211 | If the publication is an arch-indep binary, we can only supersede | ||
20 | 212 | it if all the binaries from the same source are also superseded, | ||
21 | 213 | else those binaries may become uninstallable. | ||
22 | 214 | See bug 34086. | ||
23 | 215 | """ | ||
24 | 216 | binary = publication.binarypackagerelease | ||
25 | 217 | if not binary.architecturespecific: | ||
26 | 218 | # getOtherPublicationsForSameSource returns PENDING in | ||
27 | 219 | # addition to PUBLISHED binaries, and we rely on this since | ||
28 | 220 | # they must also block domination. | ||
29 | 221 | others = publication.getOtherPublicationsForSameSource() | ||
30 | 222 | if others.any(): | ||
31 | 223 | # Don't dominate this arch:all binary as there are | ||
32 | 224 | # other arch-specific binaries from the same build | ||
33 | 225 | # that are still active. | ||
34 | 226 | return False | ||
35 | 227 | return True | ||
36 | 228 | |||
37 | 207 | def dominatePackage(self, publications, live_versions, generalization): | 229 | def dominatePackage(self, publications, live_versions, generalization): |
38 | 208 | """Dominate publications for a single package. | 230 | """Dominate publications for a single package. |
39 | 209 | 231 | ||
40 | @@ -260,7 +282,9 @@ | |||
41 | 260 | pub.supersede(current_dominant, logger=self.logger) | 282 | pub.supersede(current_dominant, logger=self.logger) |
42 | 261 | self.logger.debug2( | 283 | self.logger.debug2( |
43 | 262 | "Superseding older publication for version %s.", version) | 284 | "Superseding older publication for version %s.", version) |
45 | 263 | elif version in live_versions: | 285 | elif (version in live_versions or |
46 | 286 | (not generalization.is_source and | ||
47 | 287 | not self._checkArchIndep(pub))): | ||
48 | 264 | # This publication stays active; if any publications | 288 | # This publication stays active; if any publications |
49 | 265 | # that follow right after this are to be superseded, | 289 | # that follow right after this are to be superseded, |
50 | 266 | # this is the release that they are superseded by. | 290 | # this is the release that they are superseded by. |
51 | @@ -298,6 +322,7 @@ | |||
52 | 298 | # one, this dominatePackage call will never result in a | 322 | # one, this dominatePackage call will never result in a |
53 | 299 | # deletion. | 323 | # deletion. |
54 | 300 | latest_version = generalization.getPackageVersion(publications[0]) | 324 | latest_version = generalization.getPackageVersion(publications[0]) |
55 | 325 | self.logger.debug2("Dominating %s" % name) | ||
56 | 301 | self.dominatePackage( | 326 | self.dominatePackage( |
57 | 302 | publications, [latest_version], generalization) | 327 | publications, [latest_version], generalization) |
58 | 303 | 328 | ||
59 | @@ -359,27 +384,6 @@ | |||
60 | 359 | 384 | ||
61 | 360 | self.logger.debug("Beginning superseded processing...") | 385 | self.logger.debug("Beginning superseded processing...") |
62 | 361 | 386 | ||
63 | 362 | # XXX: dsilvers 2005-09-22 bug=55030: | ||
64 | 363 | # Need to make binaries go in groups but for now this'll do. | ||
65 | 364 | # An example of the concrete problem here is: | ||
66 | 365 | # - Upload foo-1.0, which builds foo and foo-common (arch all). | ||
67 | 366 | # - Upload foo-1.1, ditto. | ||
68 | 367 | # - foo-common-1.1 is built (along with the i386 binary for foo) | ||
69 | 368 | # - foo-common-1.0 is superseded | ||
70 | 369 | # Foo is now uninstallable on any architectures which don't yet | ||
71 | 370 | # have a build of foo-1.1, as the foo-common for foo-1.0 is gone. | ||
72 | 371 | |||
73 | 372 | # Essentially we ideally don't want to lose superseded binaries | ||
74 | 373 | # unless the entire group is ready to be made pending removal. | ||
75 | 374 | # In this instance a group is defined as all the binaries from a | ||
76 | 375 | # given build. This assumes we've copied the arch_all binaries | ||
77 | 376 | # from whichever build provided them into each arch-specific build | ||
78 | 377 | # which we publish. If instead we simply publish the arch-all | ||
79 | 378 | # binaries from another build then instead we should scan up from | ||
80 | 379 | # the binary to its source, and then back from the source to each | ||
81 | 380 | # binary published in *this* distroarchseries for that source. | ||
82 | 381 | # if the binaries as a group (in that definition) are all superseded | ||
83 | 382 | # then we can consider them eligible for removal. | ||
84 | 383 | for pub_record in binary_records: | 387 | for pub_record in binary_records: |
85 | 384 | binpkg_release = pub_record.binarypackagerelease | 388 | binpkg_release = pub_record.binarypackagerelease |
86 | 385 | self.logger.debug( | 389 | self.logger.debug( |
87 | @@ -450,19 +454,19 @@ | |||
88 | 450 | generalization = GeneralizedPublication(is_source=False) | 454 | generalization = GeneralizedPublication(is_source=False) |
89 | 451 | 455 | ||
90 | 452 | for distroarchseries in distroseries.architectures: | 456 | for distroarchseries in distroseries.architectures: |
92 | 453 | self.logger.debug( | 457 | self.logger.info( |
93 | 454 | "Performing domination across %s/%s (%s)", | 458 | "Performing domination across %s/%s (%s)", |
94 | 455 | distroseries.name, pocket.title, | 459 | distroseries.name, pocket.title, |
95 | 456 | distroarchseries.architecturetag) | 460 | distroarchseries.architecturetag) |
96 | 457 | 461 | ||
98 | 458 | bpph_location_clauses = And( | 462 | bpph_location_clauses = [ |
99 | 459 | BinaryPackagePublishingHistory.status == | 463 | BinaryPackagePublishingHistory.status == |
100 | 460 | PackagePublishingStatus.PUBLISHED, | 464 | PackagePublishingStatus.PUBLISHED, |
101 | 461 | BinaryPackagePublishingHistory.distroarchseries == | 465 | BinaryPackagePublishingHistory.distroarchseries == |
102 | 462 | distroarchseries, | 466 | distroarchseries, |
103 | 463 | BinaryPackagePublishingHistory.archive == self.archive, | 467 | BinaryPackagePublishingHistory.archive == self.archive, |
104 | 464 | BinaryPackagePublishingHistory.pocket == pocket, | 468 | BinaryPackagePublishingHistory.pocket == pocket, |
106 | 465 | ) | 469 | ] |
107 | 466 | candidate_binary_names = Select( | 470 | candidate_binary_names = Select( |
108 | 467 | BinaryPackageName.id, | 471 | BinaryPackageName.id, |
109 | 468 | And( | 472 | And( |
110 | @@ -474,7 +478,7 @@ | |||
111 | 474 | ), | 478 | ), |
112 | 475 | group_by=BinaryPackageName.id, | 479 | group_by=BinaryPackageName.id, |
113 | 476 | having=Count(BinaryPackagePublishingHistory.id) > 1) | 480 | having=Count(BinaryPackagePublishingHistory.id) > 1) |
115 | 477 | binaries = IStore(BinaryPackagePublishingHistory).find( | 481 | main_clauses = [ |
116 | 478 | BinaryPackagePublishingHistory, | 482 | BinaryPackagePublishingHistory, |
117 | 479 | BinaryPackageRelease.id == | 483 | BinaryPackageRelease.id == |
118 | 480 | BinaryPackagePublishingHistory.binarypackagereleaseID, | 484 | BinaryPackagePublishingHistory.binarypackagereleaseID, |
119 | @@ -482,10 +486,28 @@ | |||
120 | 482 | candidate_binary_names), | 486 | candidate_binary_names), |
121 | 483 | BinaryPackageRelease.binpackageformat != | 487 | BinaryPackageRelease.binpackageformat != |
122 | 484 | BinaryPackageFormat.DDEB, | 488 | BinaryPackageFormat.DDEB, |
127 | 485 | bpph_location_clauses) | 489 | ] |
128 | 486 | self.logger.debug("Dominating binaries...") | 490 | main_clauses.extend(bpph_location_clauses) |
129 | 487 | self._dominatePublications( | 491 | |
130 | 488 | self._sortPackages(binaries, generalization), generalization) | 492 | def do_domination(pass2_msg=""): |
131 | 493 | msg = "binaries..." + pass2_msg | ||
132 | 494 | self.logger.info("Finding %s" % msg) | ||
133 | 495 | bins = IStore( | ||
134 | 496 | BinaryPackagePublishingHistory).find(*main_clauses) | ||
135 | 497 | self.logger.info("Dominating %s" % msg) | ||
136 | 498 | sorted_packages = self._sortPackages(bins, generalization) | ||
137 | 499 | self._dominatePublications(sorted_packages, generalization) | ||
138 | 500 | |||
139 | 501 | do_domination() | ||
140 | 502 | |||
141 | 503 | # We need to make a second pass to cover the cases where: | ||
142 | 504 | # * arch-specific binaries were not all dominated before arch-all | ||
143 | 505 | # ones that depend on them | ||
144 | 506 | # * An arch-all turned into an arch-specific, or vice-versa | ||
145 | 507 | # * A package is completely schizophrenic and changes all of | ||
146 | 508 | # its binaries between arch-all and arch-any (apparently | ||
147 | 509 | # occurs sometimes!) | ||
148 | 510 | do_domination("(2nd pass)") | ||
149 | 489 | 511 | ||
150 | 490 | def _composeActiveSourcePubsCondition(self, distroseries, pocket): | 512 | def _composeActiveSourcePubsCondition(self, distroseries, pocket): |
151 | 491 | """Compose ORM condition for restricting relevant source pubs.""" | 513 | """Compose ORM condition for restricting relevant source pubs.""" |
152 | 492 | 514 | ||
153 | === modified file 'lib/lp/archivepublisher/tests/test_dominator.py' | |||
154 | --- lib/lp/archivepublisher/tests/test_dominator.py 2011-10-18 02:20:28 +0000 | |||
155 | +++ lib/lp/archivepublisher/tests/test_dominator.py 2011-10-18 12:00:30 +0000 | |||
156 | @@ -23,7 +23,9 @@ | |||
157 | 23 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 23 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
158 | 24 | from lp.registry.interfaces.series import SeriesStatus | 24 | from lp.registry.interfaces.series import SeriesStatus |
159 | 25 | from lp.services.log.logger import DevNullLogger | 25 | from lp.services.log.logger import DevNullLogger |
161 | 26 | from lp.soyuz.enums import PackagePublishingStatus | 26 | from lp.soyuz.enums import ( |
162 | 27 | PackagePublishingStatus, | ||
163 | 28 | ) | ||
164 | 27 | from lp.soyuz.interfaces.publishing import ISourcePackagePublishingHistory | 29 | from lp.soyuz.interfaces.publishing import ISourcePackagePublishingHistory |
165 | 28 | from lp.soyuz.tests.test_publishing import TestNativePublishingBase | 30 | from lp.soyuz.tests.test_publishing import TestNativePublishingBase |
166 | 29 | from lp.testing import ( | 31 | from lp.testing import ( |
167 | @@ -169,6 +171,136 @@ | |||
168 | 169 | dominator._dominatePublications, | 171 | dominator._dominatePublications, |
169 | 170 | pubs, GeneralizedPublication(True)) | 172 | pubs, GeneralizedPublication(True)) |
170 | 171 | 173 | ||
171 | 174 | def test_archall_domination(self): | ||
172 | 175 | # Arch-all binaries should not be dominated when a new source | ||
173 | 176 | # version builds an updated arch-all binary, because slower builds | ||
174 | 177 | # of other architectures will leave the previous version | ||
175 | 178 | # uninstallable if they depend on the arch-all binary. | ||
176 | 179 | # See https://bugs.launchpad.net/launchpad/+bug/34086 | ||
177 | 180 | |||
178 | 181 | # Set up a source, "foo" which builds "foo-bin" and foo-common | ||
179 | 182 | # (which is arch-all). | ||
180 | 183 | foo_10_src = self.getPubSource( | ||
181 | 184 | sourcename="foo", version="1.0", architecturehintlist="i386", | ||
182 | 185 | status=PackagePublishingStatus.PUBLISHED) | ||
183 | 186 | [foo_10_i386_bin] = self.getPubBinaries( | ||
184 | 187 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
185 | 188 | architecturespecific=True, version="1.0", pub_source=foo_10_src) | ||
186 | 189 | [build] = foo_10_src.getBuilds() | ||
187 | 190 | bpr = self.factory.makeBinaryPackageRelease( | ||
188 | 191 | binarypackagename="foo-common", version="1.0", build=build, | ||
189 | 192 | architecturespecific=False) | ||
190 | 193 | foo_10_all_bins = self.publishBinaryInArchive( | ||
191 | 194 | bpr, self.ubuntutest.main_archive, pocket=foo_10_src.pocket, | ||
192 | 195 | status=PackagePublishingStatus.PUBLISHED) | ||
193 | 196 | |||
194 | 197 | # Now, make version 1.1 of foo and add a foo-common but not foo-bin | ||
195 | 198 | # (imagine that it's not finished building yet). | ||
196 | 199 | foo_11_src = self.getPubSource( | ||
197 | 200 | sourcename="foo", version="1.1", architecturehintlist="all", | ||
198 | 201 | status=PackagePublishingStatus.PUBLISHED) | ||
199 | 202 | foo_11_all_bins = self.getPubBinaries( | ||
200 | 203 | binaryname="foo-common", status=PackagePublishingStatus.PUBLISHED, | ||
201 | 204 | architecturespecific=False, version="1.1", pub_source=foo_11_src) | ||
202 | 205 | |||
203 | 206 | dominator = Dominator(self.logger, self.ubuntutest.main_archive) | ||
204 | 207 | dominator.judgeAndDominate( | ||
205 | 208 | foo_10_src.distroseries, foo_10_src.pocket) | ||
206 | 209 | |||
207 | 210 | # The source will be superseded. | ||
208 | 211 | self.checkPublication(foo_10_src, PackagePublishingStatus.SUPERSEDED) | ||
209 | 212 | # The arch-specific has no dominant, so it's still published | ||
210 | 213 | self.checkPublication( | ||
211 | 214 | foo_10_i386_bin, PackagePublishingStatus.PUBLISHED) | ||
212 | 215 | # The arch-indep has a dominant but must not be superseded yet | ||
213 | 216 | # since the arch-specific is still published. | ||
214 | 217 | self.checkPublications( | ||
215 | 218 | foo_10_all_bins, PackagePublishingStatus.PUBLISHED) | ||
216 | 219 | |||
217 | 220 | # Now creating a newer foo-bin should see those last two | ||
218 | 221 | # publications superseded. | ||
219 | 222 | [build2] = foo_11_src.getBuilds() | ||
220 | 223 | foo_11_bin = self.factory.makeBinaryPackageRelease( | ||
221 | 224 | binarypackagename="foo-bin", version="1.1", build=build2, | ||
222 | 225 | architecturespecific=True) | ||
223 | 226 | self.publishBinaryInArchive( | ||
224 | 227 | foo_11_bin, self.ubuntutest.main_archive, | ||
225 | 228 | pocket=foo_10_src.pocket, | ||
226 | 229 | status=PackagePublishingStatus.PUBLISHED) | ||
227 | 230 | dominator.judgeAndDominate( | ||
228 | 231 | foo_10_src.distroseries, foo_10_src.pocket) | ||
229 | 232 | self.checkPublication( | ||
230 | 233 | foo_10_i386_bin, PackagePublishingStatus.SUPERSEDED) | ||
231 | 234 | self.checkPublications( | ||
232 | 235 | foo_10_all_bins, PackagePublishingStatus.SUPERSEDED) | ||
233 | 236 | |||
234 | 237 | def test_any_superseded_by_all(self): | ||
235 | 238 | # Set up a source, foo, which builds an architecture-dependent | ||
236 | 239 | # binary, foo-bin. | ||
237 | 240 | foo_10_src = self.getPubSource( | ||
238 | 241 | sourcename="foo", version="1.0", architecturehintlist="i386", | ||
239 | 242 | status=PackagePublishingStatus.PUBLISHED) | ||
240 | 243 | [foo_10_i386_bin] = self.getPubBinaries( | ||
241 | 244 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
242 | 245 | architecturespecific=True, version="1.0", pub_source=foo_10_src) | ||
243 | 246 | |||
244 | 247 | # Now, make version 1.1 of foo, where foo-bin is now | ||
245 | 248 | # architecture-independent. | ||
246 | 249 | foo_11_src = self.getPubSource( | ||
247 | 250 | sourcename="foo", version="1.1", architecturehintlist="all", | ||
248 | 251 | status=PackagePublishingStatus.PUBLISHED) | ||
249 | 252 | [foo_10_all_bin, foo_10_all_bin_2] = self.getPubBinaries( | ||
250 | 253 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
251 | 254 | architecturespecific=False, version="1.1", pub_source=foo_11_src) | ||
252 | 255 | |||
253 | 256 | dominator = Dominator(self.logger, self.ubuntutest.main_archive) | ||
254 | 257 | dominator.judgeAndDominate( | ||
255 | 258 | foo_10_src.distroseries, foo_10_src.pocket) | ||
256 | 259 | |||
257 | 260 | # The source will be superseded. | ||
258 | 261 | self.checkPublication(foo_10_src, PackagePublishingStatus.SUPERSEDED) | ||
259 | 262 | # The arch-specific is superseded by the new arch-indep. | ||
260 | 263 | self.checkPublication( | ||
261 | 264 | foo_10_i386_bin, PackagePublishingStatus.SUPERSEDED) | ||
262 | 265 | |||
263 | 266 | def test_schitzoid_package(self): | ||
264 | 267 | # Test domination of a source that produces an arch-indep and an | ||
265 | 268 | # arch-all, that then switches both on the next version to the | ||
266 | 269 | # other arch type. | ||
267 | 270 | foo_10_src = self.getPubSource( | ||
268 | 271 | sourcename="foo", version="1.0", architecturehintlist="i386", | ||
269 | 272 | status=PackagePublishingStatus.PUBLISHED) | ||
270 | 273 | [foo_10_i386_bin] = self.getPubBinaries( | ||
271 | 274 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
272 | 275 | architecturespecific=True, version="1.0", pub_source=foo_10_src) | ||
273 | 276 | [build] = foo_10_src.getBuilds() | ||
274 | 277 | bpr = self.factory.makeBinaryPackageRelease( | ||
275 | 278 | binarypackagename="foo-common", version="1.0", build=build, | ||
276 | 279 | architecturespecific=False) | ||
277 | 280 | foo_10_all_bins = self.publishBinaryInArchive( | ||
278 | 281 | bpr, self.ubuntutest.main_archive, pocket=foo_10_src.pocket, | ||
279 | 282 | status=PackagePublishingStatus.PUBLISHED) | ||
280 | 283 | |||
281 | 284 | foo_11_src = self.getPubSource( | ||
282 | 285 | sourcename="foo", version="1.1", architecturehintlist="i386", | ||
283 | 286 | status=PackagePublishingStatus.PUBLISHED) | ||
284 | 287 | [foo_11_i386_bin] = self.getPubBinaries( | ||
285 | 288 | binaryname="foo-common", status=PackagePublishingStatus.PUBLISHED, | ||
286 | 289 | architecturespecific=True, version="1.1", pub_source=foo_11_src) | ||
287 | 290 | [build] = foo_11_src.getBuilds() | ||
288 | 291 | bpr = self.factory.makeBinaryPackageRelease( | ||
289 | 292 | binarypackagename="foo-bin", version="1.1", build=build, | ||
290 | 293 | architecturespecific=False) | ||
291 | 294 | foo_11_all_bins = self.publishBinaryInArchive( | ||
292 | 295 | bpr, self.ubuntutest.main_archive, pocket=foo_11_src.pocket, | ||
293 | 296 | status=PackagePublishingStatus.PUBLISHED) | ||
294 | 297 | |||
295 | 298 | dominator = Dominator(self.logger, self.ubuntutest.main_archive) | ||
296 | 299 | dominator.judgeAndDominate(foo_10_src.distroseries, foo_10_src.pocket) | ||
297 | 300 | |||
298 | 301 | self.checkPublications(foo_10_all_bins + [foo_10_i386_bin], | ||
299 | 302 | PackagePublishingStatus.SUPERSEDED) | ||
300 | 303 | |||
301 | 172 | 304 | ||
302 | 173 | class TestDomination(TestNativePublishingBase): | 305 | class TestDomination(TestNativePublishingBase): |
303 | 174 | """Test overall domination procedure.""" | 306 | """Test overall domination procedure.""" |
304 | @@ -223,35 +355,6 @@ | |||
305 | 223 | self.ubuntutest['breezy-autotest'].status = ( | 355 | self.ubuntutest['breezy-autotest'].status = ( |
306 | 224 | SeriesStatus.OBSOLETE) | 356 | SeriesStatus.OBSOLETE) |
307 | 225 | 357 | ||
308 | 226 | def test_any_superseded_by_all(self): | ||
309 | 227 | # Set up a source, foo, which builds an architecture-dependent | ||
310 | 228 | # binary, foo-bin. | ||
311 | 229 | foo_10_src = self.getPubSource( | ||
312 | 230 | sourcename="foo", version="1.0", architecturehintlist="i386", | ||
313 | 231 | status=PackagePublishingStatus.PUBLISHED) | ||
314 | 232 | [foo_10_i386_bin] = self.getPubBinaries( | ||
315 | 233 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
316 | 234 | architecturespecific=True, version="1.0", pub_source=foo_10_src) | ||
317 | 235 | |||
318 | 236 | # Now, make version 1.1 of foo, where foo-bin is now | ||
319 | 237 | # architecture-independent. | ||
320 | 238 | foo_11_src = self.getPubSource( | ||
321 | 239 | sourcename="foo", version="1.1", architecturehintlist="all", | ||
322 | 240 | status=PackagePublishingStatus.PUBLISHED) | ||
323 | 241 | [foo_10_all_bin, foo_10_all_bin_2] = self.getPubBinaries( | ||
324 | 242 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
325 | 243 | architecturespecific=False, version="1.1", pub_source=foo_11_src) | ||
326 | 244 | |||
327 | 245 | dominator = Dominator(self.logger, self.ubuntutest.main_archive) | ||
328 | 246 | dominator.judgeAndDominate( | ||
329 | 247 | foo_10_src.distroseries, foo_10_src.pocket) | ||
330 | 248 | |||
331 | 249 | # The source will be superseded. | ||
332 | 250 | self.checkPublication(foo_10_src, PackagePublishingStatus.SUPERSEDED) | ||
333 | 251 | # The arch-specific is superseded by the new arch-indep. | ||
334 | 252 | self.checkPublication( | ||
335 | 253 | foo_10_i386_bin, PackagePublishingStatus.SUPERSEDED) | ||
336 | 254 | |||
337 | 255 | 358 | ||
338 | 256 | def make_spphs_for_versions(factory, versions): | 359 | def make_spphs_for_versions(factory, versions): |
339 | 257 | """Create publication records for each of `versions`. | 360 | """Create publication records for each of `versions`. |
340 | 258 | 361 | ||
341 | === modified file 'lib/lp/soyuz/model/publishing.py' | |||
342 | --- lib/lp/soyuz/model/publishing.py 2011-10-18 02:09:38 +0000 | |||
343 | +++ lib/lp/soyuz/model/publishing.py 2011-10-18 12:00:30 +0000 | |||
344 | @@ -33,6 +33,7 @@ | |||
345 | 33 | Desc, | 33 | Desc, |
346 | 34 | LeftJoin, | 34 | LeftJoin, |
347 | 35 | Or, | 35 | Or, |
348 | 36 | Select, | ||
349 | 36 | Sum, | 37 | Sum, |
350 | 37 | ) | 38 | ) |
351 | 38 | from storm.store import Store | 39 | from storm.store import Store |
352 | @@ -1118,6 +1119,60 @@ | |||
353 | 1118 | section=self.section, | 1119 | section=self.section, |
354 | 1119 | priority=self.priority) | 1120 | priority=self.priority) |
355 | 1120 | 1121 | ||
356 | 1122 | def getOtherPublicationsForSameSource(self, include_archindep=False): | ||
357 | 1123 | """Return all the other published or pending binaries for this | ||
358 | 1124 | source. | ||
359 | 1125 | |||
360 | 1126 | For example if source package foo builds: | ||
361 | 1127 | foo - i386 | ||
362 | 1128 | foo - amd64 | ||
363 | 1129 | foo-common - arch-all (published in i386 and amd64) | ||
364 | 1130 | then if this publication is the arch-all amd64, return foo(i386), | ||
365 | 1131 | foo(amd64). If include_archindep is True then also return | ||
366 | 1132 | foo-common (i386) | ||
367 | 1133 | |||
368 | 1134 | :param include_archindep: If True, return architecture independent | ||
369 | 1135 | publications too. Defaults to False. | ||
370 | 1136 | |||
371 | 1137 | :return: an iterable of `BinaryPackagePublishingHistory` | ||
372 | 1138 | """ | ||
373 | 1139 | # Avoid circular wotsits. | ||
374 | 1140 | from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild | ||
375 | 1141 | from lp.soyuz.model.distroarchseries import DistroArchSeries | ||
376 | 1142 | from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease | ||
377 | 1143 | source_select = Select( | ||
378 | 1144 | SourcePackageRelease.id, | ||
379 | 1145 | And( | ||
380 | 1146 | BinaryPackageBuild.source_package_release_id == | ||
381 | 1147 | SourcePackageRelease.id, | ||
382 | 1148 | BinaryPackageRelease.build == BinaryPackageBuild.id, | ||
383 | 1149 | self.binarypackagereleaseID == BinaryPackageRelease.id, | ||
384 | 1150 | )) | ||
385 | 1151 | pubs = [ | ||
386 | 1152 | BinaryPackageBuild.source_package_release_id == | ||
387 | 1153 | SourcePackageRelease.id, | ||
388 | 1154 | SourcePackageRelease.id.is_in(source_select), | ||
389 | 1155 | BinaryPackageRelease.build == BinaryPackageBuild.id, | ||
390 | 1156 | BinaryPackagePublishingHistory.binarypackagereleaseID == | ||
391 | 1157 | BinaryPackageRelease.id, | ||
392 | 1158 | BinaryPackagePublishingHistory.archiveID == self.archive.id, | ||
393 | 1159 | BinaryPackagePublishingHistory.distroarchseriesID == | ||
394 | 1160 | DistroArchSeries.id, | ||
395 | 1161 | DistroArchSeries.distroseriesID == self.distroseries.id, | ||
396 | 1162 | BinaryPackagePublishingHistory.pocket == self.pocket, | ||
397 | 1163 | BinaryPackagePublishingHistory.status.is_in( | ||
398 | 1164 | active_publishing_status), | ||
399 | 1165 | BinaryPackagePublishingHistory.id != self.id | ||
400 | 1166 | ] | ||
401 | 1167 | |||
402 | 1168 | if not include_archindep: | ||
403 | 1169 | pubs.append(BinaryPackageRelease.architecturespecific == True) | ||
404 | 1170 | |||
405 | 1171 | return IMasterStore(BinaryPackagePublishingHistory).find( | ||
406 | 1172 | BinaryPackagePublishingHistory, | ||
407 | 1173 | *pubs | ||
408 | 1174 | ) | ||
409 | 1175 | |||
410 | 1121 | def supersede(self, dominant=None, logger=None): | 1176 | def supersede(self, dominant=None, logger=None): |
411 | 1122 | """See `IBinaryPackagePublishingHistory`.""" | 1177 | """See `IBinaryPackagePublishingHistory`.""" |
412 | 1123 | # At this point only PUBLISHED (ancient versions) or PENDING ( | 1178 | # At this point only PUBLISHED (ancient versions) or PENDING ( |
413 | 1124 | 1179 | ||
414 | === modified file 'lib/lp/soyuz/tests/test_publishing.py' | |||
415 | --- lib/lp/soyuz/tests/test_publishing.py 2011-10-18 02:09:38 +0000 | |||
416 | +++ lib/lp/soyuz/tests/test_publishing.py 2011-10-18 12:00:30 +0000 | |||
417 | @@ -1471,6 +1471,112 @@ | |||
418 | 1471 | self.assertEquals(spph.ancestor.displayname, ancestor.displayname) | 1471 | self.assertEquals(spph.ancestor.displayname, ancestor.displayname) |
419 | 1472 | 1472 | ||
420 | 1473 | 1473 | ||
421 | 1474 | class TestGetOtherPublicationsForSameSource(TestNativePublishingBase): | ||
422 | 1475 | """Test parts of the BinaryPackagePublishingHistory model. | ||
423 | 1476 | |||
424 | 1477 | See also lib/lp/soyuz/doc/publishing.txt | ||
425 | 1478 | """ | ||
426 | 1479 | |||
427 | 1480 | layer = LaunchpadZopelessLayer | ||
428 | 1481 | |||
429 | 1482 | def _makeMixedSingleBuildPackage(self, version="1.0"): | ||
430 | 1483 | # Set up a source with a build that generated four binaries, | ||
431 | 1484 | # two of them an arch-all. | ||
432 | 1485 | foo_src_pub = self.getPubSource( | ||
433 | 1486 | sourcename="foo", version=version, architecturehintlist="i386", | ||
434 | 1487 | status=PackagePublishingStatus.PUBLISHED) | ||
435 | 1488 | [foo_bin_pub] = self.getPubBinaries( | ||
436 | 1489 | binaryname="foo-bin", status=PackagePublishingStatus.PUBLISHED, | ||
437 | 1490 | architecturespecific=True, version=version, | ||
438 | 1491 | pub_source=foo_src_pub) | ||
439 | 1492 | # Now need to grab the build for the source so we can add | ||
440 | 1493 | # more binaries to it. | ||
441 | 1494 | [build] = foo_src_pub.getBuilds() | ||
442 | 1495 | foo_one_common = self.factory.makeBinaryPackageRelease( | ||
443 | 1496 | binarypackagename="foo-one-common", version=version, build=build, | ||
444 | 1497 | architecturespecific=False) | ||
445 | 1498 | foo_one_common_pubs = self.publishBinaryInArchive( | ||
446 | 1499 | foo_one_common, self.ubuntutest.main_archive, | ||
447 | 1500 | pocket=foo_src_pub.pocket, | ||
448 | 1501 | status=PackagePublishingStatus.PUBLISHED) | ||
449 | 1502 | foo_two_common = self.factory.makeBinaryPackageRelease( | ||
450 | 1503 | binarypackagename="foo-two-common", version=version, build=build, | ||
451 | 1504 | architecturespecific=False) | ||
452 | 1505 | foo_two_common_pubs = self.publishBinaryInArchive( | ||
453 | 1506 | foo_two_common, self.ubuntutest.main_archive, | ||
454 | 1507 | pocket=foo_src_pub.pocket, | ||
455 | 1508 | status=PackagePublishingStatus.PUBLISHED) | ||
456 | 1509 | foo_three = self.factory.makeBinaryPackageRelease( | ||
457 | 1510 | binarypackagename="foo-three", version=version, build=build, | ||
458 | 1511 | architecturespecific=True) | ||
459 | 1512 | [foo_three_pub] = self.publishBinaryInArchive( | ||
460 | 1513 | foo_three, self.ubuntutest.main_archive, | ||
461 | 1514 | pocket=foo_src_pub.pocket, | ||
462 | 1515 | status=PackagePublishingStatus.PUBLISHED) | ||
463 | 1516 | # So now we have source foo, which has arch specific binaries | ||
464 | 1517 | # foo-bin and foo-three, and arch:all binaries foo-one-common and | ||
465 | 1518 | # foo-two-common. The latter two will have multiple publications, | ||
466 | 1519 | # one for each DAS in the series. | ||
467 | 1520 | return ( | ||
468 | 1521 | foo_src_pub, foo_bin_pub, foo_one_common_pubs, | ||
469 | 1522 | foo_two_common_pubs, foo_three_pub) | ||
470 | 1523 | |||
471 | 1524 | def test_getOtherPublicationsForSameSource(self): | ||
472 | 1525 | # By default getOtherPublicationsForSameSource should return all | ||
473 | 1526 | # of the other binaries built by the same source as the passed | ||
474 | 1527 | # binary publication, except the arch-indep ones. | ||
475 | 1528 | (foo_src_pub, foo_bin_pub, foo_one_common_pubs, foo_two_common_pubs, | ||
476 | 1529 | foo_three_pub) = self._makeMixedSingleBuildPackage() | ||
477 | 1530 | |||
478 | 1531 | foo_one_common_pub = foo_one_common_pubs[0] | ||
479 | 1532 | others = foo_one_common_pub.getOtherPublicationsForSameSource() | ||
480 | 1533 | others = list(others) | ||
481 | 1534 | |||
482 | 1535 | self.assertContentEqual([foo_three_pub, foo_bin_pub], others) | ||
483 | 1536 | |||
484 | 1537 | def test_getOtherPublicationsForSameSource_include_archindep(self): | ||
485 | 1538 | # Check that the arch-indep binaries are returned if requested. | ||
486 | 1539 | (foo_src_pub, foo_bin_pub, foo_one_common_pubs, foo_two_common_pubs, | ||
487 | 1540 | foo_three_pub) = self._makeMixedSingleBuildPackage() | ||
488 | 1541 | |||
489 | 1542 | foo_one_common_pub = foo_one_common_pubs[0] | ||
490 | 1543 | others = foo_one_common_pub.getOtherPublicationsForSameSource( | ||
491 | 1544 | include_archindep=True) | ||
492 | 1545 | others = list(others) | ||
493 | 1546 | |||
494 | 1547 | # We expect all publications created above to be returned, | ||
495 | 1548 | # except the one we use to call the method on. | ||
496 | 1549 | expected = [foo_three_pub, foo_bin_pub] | ||
497 | 1550 | expected.extend(foo_one_common_pubs[1:]) | ||
498 | 1551 | expected.extend(foo_two_common_pubs) | ||
499 | 1552 | self.assertContentEqual(expected, others) | ||
500 | 1553 | |||
501 | 1554 | def test_getOtherPublicationsForSameSource_inactive(self): | ||
502 | 1555 | # Check that inactive publications are not returned. | ||
503 | 1556 | (foo_src_pub, foo_bin_pub, foo_one_common_pubs, foo_two_common_pubs, | ||
504 | 1557 | foo_three_pub) = self._makeMixedSingleBuildPackage() | ||
505 | 1558 | foo_bin_pub.status = PackagePublishingStatus.SUPERSEDED | ||
506 | 1559 | foo_three_pub.status = PackagePublishingStatus.SUPERSEDED | ||
507 | 1560 | foo_one_common_pub = foo_one_common_pubs[0] | ||
508 | 1561 | others = foo_one_common_pub.getOtherPublicationsForSameSource() | ||
509 | 1562 | others = list(others) | ||
510 | 1563 | |||
511 | 1564 | self.assertEqual(0, len(others)) | ||
512 | 1565 | |||
513 | 1566 | def test_getOtherPublicationsForSameSource_multiple_versions(self): | ||
514 | 1567 | # Check that publications for only the same version as the | ||
515 | 1568 | # context binary publication are returned. | ||
516 | 1569 | (foo_src_pub, foo_bin_pub, foo_one_common_pubs, foo_two_common_pubs, | ||
517 | 1570 | foo_three_pub) = self._makeMixedSingleBuildPackage(version="1.0") | ||
518 | 1571 | self._makeMixedSingleBuildPackage(version="1.1") | ||
519 | 1572 | |||
520 | 1573 | foo_one_common_pub = foo_one_common_pubs[0] | ||
521 | 1574 | others = foo_one_common_pub.getOtherPublicationsForSameSource() | ||
522 | 1575 | others = list(others) | ||
523 | 1576 | |||
524 | 1577 | self.assertContentEqual([foo_three_pub, foo_bin_pub], others) | ||
525 | 1578 | |||
526 | 1579 | |||
527 | 1474 | class TestGetBuiltBinaries(TestNativePublishingBase): | 1580 | class TestGetBuiltBinaries(TestNativePublishingBase): |
528 | 1475 | """Test SourcePackagePublishingHistory.getBuiltBinaries() works.""" | 1581 | """Test SourcePackagePublishingHistory.getBuiltBinaries() works.""" |
529 | 1476 | 1582 |