Merge lp:~michael.nelson/launchpad/475808-unembargoing-oops into lp:launchpad/db-devel
- 475808-unembargoing-oops
- Merge into db-devel
Proposed by
Michael Nelson
Status: | Merged |
---|---|
Approved by: | Aaron Bentley |
Approved revision: | not available |
Merged at revision: | not available |
Proposed branch: | lp:~michael.nelson/launchpad/475808-unembargoing-oops |
Merge into: | lp:launchpad/db-devel |
Diff against target: |
405 lines (+208/-63) 4 files modified
lib/lp/soyuz/interfaces/publishing.py (+28/-0) lib/lp/soyuz/model/publishing.py (+29/-22) lib/lp/soyuz/model/queue.py (+41/-6) lib/lp/soyuz/scripts/tests/test_copypackage.py (+110/-35) |
To merge this branch: | bzr merge lp:~michael.nelson/launchpad/475808-unembargoing-oops |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Данило Шеган (community) | release-critical | Approve | |
Aaron Bentley (community) | Approve | ||
Review via email: mp+16141@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote : | # |
Revision history for this message
Данило Шеган (danilo) : | # |
review:
Approve
(release-critical)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/soyuz/interfaces/publishing.py' |
2 | --- lib/lp/soyuz/interfaces/publishing.py 2009-12-12 03:25:27 +0000 |
3 | +++ lib/lp/soyuz/interfaces/publishing.py 2009-12-21 09:19:13 +0000 |
4 | @@ -1139,6 +1139,34 @@ |
5 | the source_package_pub, allowing the use of the cached results. |
6 | """ |
7 | |
8 | + def getNearestAncestor( |
9 | + package_name, archive, distroseries, pocket=None, status=None, |
10 | + binary=False): |
11 | + """Return the ancestor of the given parkage in a particular archive. |
12 | + |
13 | + :param package_name: The package name for which we are checking for |
14 | + an ancestor. |
15 | + :type package_name: ``string`` |
16 | + :param archive: The archive in which we are looking for an ancestor. |
17 | + :type archive: `IArchive` |
18 | + :param distroseries: The particular series in which we are looking for |
19 | + an ancestor. |
20 | + :type distroseries: `IDistroSeries` |
21 | + :param pocket: An optional pocket to restrict the search. |
22 | + :type pocket: `PackagePublishingPocket`. |
23 | + :param status: An optional status defaulting to PUBLISHED if not |
24 | + provided. |
25 | + :type status: `PackagePublishingStatus` |
26 | + :param binary: An optional argument to look for a binary ancestor |
27 | + instead of the default source. |
28 | + :type binary: ``Boolean`` |
29 | + |
30 | + :return: The most recent publishing history for the given |
31 | + arguments. |
32 | + :rtype: `ISourcePackagePublishingHistory` or |
33 | + `IBinaryPackagePublishingHistory` or None. |
34 | + """ |
35 | + |
36 | active_publishing_status = ( |
37 | PackagePublishingStatus.PENDING, |
38 | PackagePublishingStatus.PUBLISHED, |
39 | |
40 | === modified file 'lib/lp/soyuz/model/publishing.py' |
41 | --- lib/lp/soyuz/model/publishing.py 2009-12-14 13:49:03 +0000 |
42 | +++ lib/lp/soyuz/model/publishing.py 2009-12-21 09:19:13 +0000 |
43 | @@ -835,17 +835,10 @@ |
44 | archive = self.archive |
45 | if distroseries is None: |
46 | distroseries = self.distroseries |
47 | - if status is None: |
48 | - status = PackagePublishingStatus.PUBLISHED |
49 | - |
50 | - ancestries = archive.getPublishedSources( |
51 | - name=self.source_package_name, exact_match=True, |
52 | - status=status, distroseries=distroseries, pocket=pocket) |
53 | - |
54 | - if ancestries.count() > 0: |
55 | - return ancestries[0] |
56 | - |
57 | - return None |
58 | + |
59 | + return getUtility(IPublishingSet).getNearestAncestor( |
60 | + self.source_package_name, archive, distroseries, pocket, |
61 | + status) |
62 | |
63 | def overrideFromAncestry(self): |
64 | """See `ISourcePackagePublishingHistory`.""" |
65 | @@ -1101,17 +1094,10 @@ |
66 | archive = self.archive |
67 | if distroseries is None: |
68 | distroseries = self.distroarchseries.distroseries |
69 | - if status is None: |
70 | - status = PackagePublishingStatus.PUBLISHED |
71 | - |
72 | - ancestries = archive.getAllPublishedBinaries( |
73 | - name=self.binary_package_name, exact_match=True, pocket=pocket, |
74 | - status=status, distroarchseries=distroseries.architectures) |
75 | - |
76 | - if ancestries.count() > 0: |
77 | - return ancestries[0] |
78 | - |
79 | - return None |
80 | + |
81 | + return getUtility(IPublishingSet).getNearestAncestor( |
82 | + self.binary_package_name, archive, distroseries, pocket, |
83 | + status, binary=True) |
84 | |
85 | def overrideFromAncestry(self): |
86 | """See `IBinaryPackagePublishingHistory`.""" |
87 | @@ -1699,3 +1685,24 @@ |
88 | store.execute(query) |
89 | |
90 | return sources + binary_packages |
91 | + |
92 | + def getNearestAncestor( |
93 | + self, package_name, archive, distroseries, pocket=None, |
94 | + status=None, binary=False): |
95 | + """See `IPublishingSet`.""" |
96 | + if status is None: |
97 | + status = PackagePublishingStatus.PUBLISHED |
98 | + |
99 | + if binary: |
100 | + ancestries = archive.getAllPublishedBinaries( |
101 | + name=package_name, exact_match=True, pocket=pocket, |
102 | + status=status, distroarchseries=distroseries.architectures) |
103 | + else: |
104 | + ancestries = archive.getPublishedSources( |
105 | + name=package_name, exact_match=True, pocket=pocket, |
106 | + status=status, distroseries=distroseries) |
107 | + |
108 | + if ancestries.count() > 0: |
109 | + return ancestries[0] |
110 | + |
111 | + return None |
112 | |
113 | === modified file 'lib/lp/soyuz/model/queue.py' |
114 | --- lib/lp/soyuz/model/queue.py 2009-12-14 13:49:03 +0000 |
115 | +++ lib/lp/soyuz/model/queue.py 2009-12-21 09:19:13 +0000 |
116 | @@ -18,8 +18,8 @@ |
117 | import StringIO |
118 | import tempfile |
119 | |
120 | -from email.MIMEMultipart import MIMEMultipart |
121 | -from email.MIMEText import MIMEText |
122 | +from email.mime.multipart import MIMEMultipart |
123 | +from email.mime.text import MIMEText |
124 | |
125 | from storm.locals import Desc, In, Join |
126 | from storm.store import Store |
127 | @@ -546,7 +546,8 @@ |
128 | # it's available. |
129 | changes_file = None |
130 | if ISourcePackagePublishingHistory.providedBy(pub_record): |
131 | - changes_file = pub_record.sourcepackagerelease.package_upload.changesfile |
132 | + release = pub_record.sourcepackagerelease |
133 | + changes_file = release.package_upload.changesfile |
134 | |
135 | for new_file in update_files_privacy(pub_record): |
136 | debug(logger, |
137 | @@ -561,7 +562,8 @@ |
138 | debug( |
139 | logger, |
140 | "sending email to %s" % self.distroseries.changeslist) |
141 | - changes_file_object = StringIO.StringIO(changes_file.read()) |
142 | + changes_file_object = StringIO.StringIO( |
143 | + changes_file.read()) |
144 | self.notify( |
145 | announce_list=self.distroseries.changeslist, |
146 | changes_file_object=changes_file_object, |
147 | @@ -1303,9 +1305,28 @@ |
148 | def checkComponentAndSection(self): |
149 | """See `IPackageUploadBuild`.""" |
150 | distroseries = self.packageupload.distroseries |
151 | + is_ppa = self.packageupload.archive.is_ppa |
152 | + is_delayed_copy = self.packageupload.is_delayed_copy |
153 | + |
154 | for binary in self.build.binarypackages: |
155 | - if (not self.packageupload.archive.is_ppa and |
156 | - binary.component not in distroseries.upload_components): |
157 | + component = binary.component |
158 | + |
159 | + if is_delayed_copy: |
160 | + # For a delayed copy the component will not yet have |
161 | + # had the chance to be overridden, so we'll check the value |
162 | + # that will be overridden by querying the ancestor in |
163 | + # the destination archive - if one is available. |
164 | + binary_name = binary.name |
165 | + ancestry = getUtility(IPublishingSet).getNearestAncestor( |
166 | + package_name=binary_name, |
167 | + archive=self.packageupload.archive, |
168 | + distroseries=self.packageupload.distroseries, binary=True) |
169 | + |
170 | + if ancestry is not None: |
171 | + component = ancestry.component |
172 | + |
173 | + if (not is_ppa and component not in |
174 | + distroseries.upload_components): |
175 | # Only complain about non-PPA uploads. |
176 | raise QueueBuildAcceptError( |
177 | 'Component "%s" is not allowed in %s' |
178 | @@ -1491,6 +1512,20 @@ |
179 | component = self.sourcepackagerelease.component |
180 | section = self.sourcepackagerelease.section |
181 | |
182 | + if self.packageupload.is_delayed_copy: |
183 | + # For a delayed copy the component will not yet have |
184 | + # had the chance to be overridden, so we'll check the value |
185 | + # that will be overridden by querying the ancestor in |
186 | + # the destination archive - if one is available. |
187 | + source_name = self.sourcepackagerelease.name |
188 | + ancestry = getUtility(IPublishingSet).getNearestAncestor( |
189 | + package_name=source_name, |
190 | + archive=self.packageupload.archive, |
191 | + distroseries=self.packageupload.distroseries) |
192 | + |
193 | + if ancestry is not None: |
194 | + component = ancestry.component |
195 | + |
196 | if (not self.packageupload.archive.is_ppa and |
197 | component not in distroseries.upload_components): |
198 | # Only complain about non-PPA uploads. |
199 | |
200 | === modified file 'lib/lp/soyuz/scripts/tests/test_copypackage.py' |
201 | --- lib/lp/soyuz/scripts/tests/test_copypackage.py 2009-12-14 13:49:03 +0000 |
202 | +++ lib/lp/soyuz/scripts/tests/test_copypackage.py 2009-12-21 09:19:13 +0000 |
203 | @@ -36,7 +36,8 @@ |
204 | IBinaryPackagePublishingHistory, ISourcePackagePublishingHistory, |
205 | PackagePublishingStatus, active_publishing_status) |
206 | from lp.soyuz.interfaces.queue import ( |
207 | - PackageUploadCustomFormat, PackageUploadStatus) |
208 | + PackageUploadCustomFormat, PackageUploadStatus, |
209 | + QueueInconsistentStateError) |
210 | from lp.soyuz.interfaces.sourcepackageformat import ( |
211 | ISourcePackageFormatSelectionSet, SourcePackageFormat) |
212 | from lp.soyuz.model.publishing import ( |
213 | @@ -937,14 +938,23 @@ |
214 | super(DoDelayedCopyTestCase, self).setUp() |
215 | self.test_publisher = SoyuzTestPublisher() |
216 | |
217 | + # Setup to copy into the main archive security pocket |
218 | + self.test_publisher.prepareBreezyAutotest() |
219 | + self.copy_archive = self.test_publisher.ubuntutest.main_archive |
220 | + self.copy_series = self.test_publisher.distroseries |
221 | + self.copy_pocket = PackagePublishingPocket.SECURITY |
222 | + |
223 | + # Make ubuntutest/breezy-autotest CURRENT so uploads to SECURITY |
224 | + # pocket can be accepted. |
225 | + self.test_publisher.breezy_autotest.status = ( |
226 | + DistroSeriesStatus.CURRENT) |
227 | + |
228 | def createDelayedCopyContext(self): |
229 | """Create a context to allow delayed-copies test. |
230 | |
231 | The returned source publication in a private archive with |
232 | binaries and a custom upload. |
233 | """ |
234 | - self.test_publisher.prepareBreezyAutotest() |
235 | - |
236 | ppa = self.factory.makeArchive( |
237 | distribution=self.test_publisher.ubuntutest, |
238 | purpose=ArchivePurpose.PPA) |
239 | @@ -959,34 +969,32 @@ |
240 | build.package_upload.addCustom( |
241 | custom_file, PackageUploadCustomFormat.DIST_UPGRADER) |
242 | |
243 | + # Commit for making the just-create library files available. |
244 | + self.layer.txn.commit() |
245 | + |
246 | return source |
247 | |
248 | + def do_delayed_copy(self, source): |
249 | + """Execute and return the delayed copy.""" |
250 | + |
251 | + self.layer.switchDbUser(self.dbuser) |
252 | + |
253 | + delayed_copy = _do_delayed_copy( |
254 | + source, self.copy_archive, self.copy_series, self.copy_pocket, |
255 | + True) |
256 | + |
257 | + self.layer.txn.commit() |
258 | + self.layer.switchDbUser('launchpad') |
259 | + return delayed_copy |
260 | + |
261 | def test_do_delayed_copy_simple(self): |
262 | # _do_delayed_copy() return an `IPackageUpload` record configured |
263 | # as a delayed-copy and with the expected contents (source, |
264 | # binaries and custom uploads) in ACCEPTED state. |
265 | - |
266 | source = self.createDelayedCopyContext() |
267 | |
268 | - # Make ubuntutest/breezy-autotest CURRENT so uploads to SECURITY |
269 | - # pocket can be accepted. |
270 | - self.test_publisher.breezy_autotest.status = ( |
271 | - DistroSeriesStatus.CURRENT) |
272 | - |
273 | # Setup and execute the delayed copy procedure. |
274 | - copy_archive = self.test_publisher.ubuntutest.main_archive |
275 | - copy_series = source.distroseries |
276 | - copy_pocket = PackagePublishingPocket.SECURITY |
277 | - |
278 | - # Commit for making the just-create library files available. |
279 | - self.layer.txn.commit() |
280 | - self.layer.switchDbUser(self.dbuser) |
281 | - |
282 | - delayed_copy = _do_delayed_copy( |
283 | - source, copy_archive, copy_series, copy_pocket, True) |
284 | - |
285 | - self.layer.txn.commit() |
286 | - self.layer.switchDbUser('launchpad') |
287 | + delayed_copy = self.do_delayed_copy(source) |
288 | |
289 | # A delayed-copy `IPackageUpload` record is returned. |
290 | self.assertTrue(delayed_copy.is_delayed_copy) |
291 | @@ -1001,9 +1009,82 @@ |
292 | delayed_copy.displayname) |
293 | |
294 | # It is targeted to the right publishing context. |
295 | - self.assertEquals(copy_archive, delayed_copy.archive) |
296 | - self.assertEquals(copy_series, delayed_copy.distroseries) |
297 | - self.assertEquals(copy_pocket, delayed_copy.pocket) |
298 | + self.assertEquals(self.copy_archive, delayed_copy.archive) |
299 | + self.assertEquals(self.copy_series, delayed_copy.distroseries) |
300 | + self.assertEquals(self.copy_pocket, delayed_copy.pocket) |
301 | + |
302 | + # And it contains the source, build and custom files. |
303 | + self.assertEquals( |
304 | + [source.sourcepackagerelease], |
305 | + [pus.sourcepackagerelease for pus in delayed_copy.sources]) |
306 | + |
307 | + [build] = source.getBuilds() |
308 | + self.assertEquals( |
309 | + [build], |
310 | + [pub.build for pub in delayed_copy.builds]) |
311 | + |
312 | + [custom_file] = [ |
313 | + custom.libraryfilealias |
314 | + for custom in build.package_upload.customfiles] |
315 | + self.assertEquals( |
316 | + [custom_file], |
317 | + [custom.libraryfilealias for custom in delayed_copy.customfiles]) |
318 | + |
319 | + def test_do_delayed_copy_wrong_component_no_ancestry(self): |
320 | + """An original PPA upload for an invalid component will have been |
321 | + overridden when uploaded to the PPA, but when copying it to another |
322 | + archive, only the ancestry in the destination archive can be used. |
323 | + If that ancestry doesn't exist, an exception is raised.""" |
324 | + # We'll simulate an upload that was overridden to main in the |
325 | + # ppa, by explicitly setting the spr's and bpr's component to |
326 | + # something else. |
327 | + source = self.createDelayedCopyContext() |
328 | + contrib = getUtility(IComponentSet).new('contrib') |
329 | + source.sourcepackagerelease.component = contrib |
330 | + [build] = source.getBuilds() |
331 | + [binary] = build.binarypackages |
332 | + binary.override(component=contrib) |
333 | + self.layer.txn.commit() |
334 | + |
335 | + # Setup and execute the delayed copy procedure. This should |
336 | + # raise an exception, as it won't be able to find an ancestor |
337 | + # whose component can be used for overriding. |
338 | + do_delayed_copy_method = self.do_delayed_copy |
339 | + self.assertRaises( |
340 | + QueueInconsistentStateError, do_delayed_copy_method, source) |
341 | + |
342 | + def test_do_delayed_copy_wrong_component_with_ancestry(self): |
343 | + """An original PPA upload for an invalid component will have been |
344 | + overridden when uploaded to the PPA, but when copying it to another |
345 | + archive, only the ancestry in the destination archive can be used. |
346 | + If an ancestor is found in the destination archive, its component |
347 | + is assumed for this package upload.""" |
348 | + # We'll simulate an upload that was overridden to main in the |
349 | + # ppa, by explicitly setting the spr's and bpr's component to |
350 | + # something else. |
351 | + source = self.createDelayedCopyContext() |
352 | + contrib = getUtility(IComponentSet).new('contrib') |
353 | + source.sourcepackagerelease.component = contrib |
354 | + [build] = source.getBuilds() |
355 | + [binary] = build.binarypackages |
356 | + binary.override(component=contrib) |
357 | + |
358 | + # This time, we'll ensure that there is already an ancestor for |
359 | + # foocom in the destination archive with binaries. |
360 | + ancestor = self.test_publisher.getPubSource( |
361 | + 'foocomm', '0.9', component='multiverse', |
362 | + archive=self.copy_archive, |
363 | + status=PackagePublishingStatus.PUBLISHED) |
364 | + ancestor_bins = self.test_publisher.getPubBinaries( |
365 | + binaryname='foo-bin', archive=self.copy_archive, |
366 | + status=PackagePublishingStatus.PUBLISHED, pub_source=ancestor) |
367 | + self.layer.txn.commit() |
368 | + |
369 | + # Setup and execute the delayed copy procedure. This should |
370 | + # now result in an accepted delayed upload. |
371 | + delayed_copy = self.do_delayed_copy(source) |
372 | + self.assertEquals( |
373 | + PackageUploadStatus.ACCEPTED, delayed_copy.status) |
374 | |
375 | # And it contains the source, build and custom files. |
376 | self.assertEquals( |
377 | @@ -1055,6 +1136,9 @@ |
378 | changes_file_name=changes_file_name) |
379 | package_upload.addBuild(build_i386) |
380 | |
381 | + # Commit for making the just-create library files available. |
382 | + self.layer.txn.commit() |
383 | + |
384 | return source |
385 | |
386 | def test_do_delayed_copy_of_partially_built_sources(self): |
387 | @@ -1062,17 +1146,8 @@ |
388 | # the FULLYBUILT builds are copied. |
389 | source = self.createPartiallyBuiltDelayedCopyContext() |
390 | |
391 | - # Setup and execute the delayed copy procedure. |
392 | - copy_archive = self.test_publisher.ubuntutest.main_archive |
393 | - copy_series = source.distroseries |
394 | - copy_pocket = PackagePublishingPocket.RELEASE |
395 | - |
396 | - # Make new libraryfiles available by committing the transaction. |
397 | - self.layer.txn.commit() |
398 | - |
399 | # Perform the delayed-copy including binaries. |
400 | - delayed_copy = _do_delayed_copy( |
401 | - source, copy_archive, copy_series, copy_pocket, True) |
402 | + delayed_copy = self.do_delayed_copy(source) |
403 | |
404 | # Only the i386 build is included in the delayed-copy. |
405 | # For the record, later on, when the delayed-copy gets processed, |
= Summary =
We need to check which component a delayed copy *will* be overridden to, when accepting it, rather than relying on the spr.component. This is a fix for bug 475808.
== Proposed fix ==
This branch ensures that when the component of a delayed_copy is checked before accepting it, the ancestry component is taken into account (as we can't actually do the component override until we publish the source package publishing history).
== Pre-implementation notes ==
See the pre-imp notes on bug 475808
== Implementation details ==
== Tests ==
bin/test -vvt DoDelayedCopyTe stCase
== Demo and Q/A ==
We will need to Q/A this on dogfood.
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: soyuz/model/ queue.py soyuz/scripts/ tests/test_ copypackage. py
lib/lp/
lib/lp/
== Pylint notices ==
lib/lp/ soyuz/model/ queue.py MIMEMultipart' (No module named MIMEMultipart)
21: [F0401] Unable to import 'email.
22: [F0401] Unable to import 'email.MIMEText' (No module named MIMEText)
--
Michael