Merge lp:~jelmer/launchpad/135610-duplicated-ancestry into lp:launchpad

Proposed by Jelmer Vernooij
Status: Merged
Approved by: Paul Hummer
Approved revision: no longer in the source branch.
Merged at revision: 11746
Proposed branch: lp:~jelmer/launchpad/135610-duplicated-ancestry
Merge into: lp:launchpad
Diff against target: 347 lines (+129/-122)
4 files modified
lib/lp/archiveuploader/nascentuploadfile.py (+12/-33)
lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt (+8/-3)
lib/lp/archiveuploader/tests/nascentupload.txt (+11/-85)
lib/lp/archiveuploader/tests/test_nascentuploadfile.py (+98/-1)
To merge this branch: bzr merge lp:~jelmer/launchpad/135610-duplicated-ancestry
Reviewer Review Type Date Requested Status
Paul Hummer (community) Approve
Launchpad code reviewers code Pending
Review via email: mp+38444@code.launchpad.net

Commit message

Allow extra PENDING source package publishing history entries in NascentUploadFile.findSourcePackageRelease.

Description of the change

This patch fixes findSourcePackageRelease() to deal with multiple source package publishing entries for a package/version tuple.

Previously we only supported a single spph for a particular package/version - if there were more we would raise an AssertionError. We now only raise an AssertionError if there is more than one PUBLISHED spph record. Multiple PENDING records are fine.

This branch also cleans up some tech debt by removing a code path in findSourcePackageRelease that is not used (or planned to be used) in production. Source packages have to be published now before findSourcePackageRelease can find them; the only situation where this wouldn't be the case is in some of the nascent upload tests, which I have fixed.

To post a comment you must log in.
Revision history for this message
Paul Hummer (rockstar) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/archiveuploader/nascentuploadfile.py'
2--- lib/lp/archiveuploader/nascentuploadfile.py 2010-10-02 11:41:43 +0000
3+++ lib/lp/archiveuploader/nascentuploadfile.py 2010-10-14 18:06:51 +0000
4@@ -50,8 +50,8 @@
5 from lp.soyuz.enums import (
6 BinaryPackageFormat,
7 PackagePublishingPriority,
8+ PackagePublishingStatus,
9 PackageUploadCustomFormat,
10- PackageUploadStatus,
11 )
12 from lp.soyuz.interfaces.binarypackagename import IBinaryPackageNameSet
13 from lp.soyuz.interfaces.component import IComponentSet
14@@ -781,11 +781,9 @@
15 # Database relationship methods
16 #
17 def findSourcePackageRelease(self):
18- """Return the respective ISourcePackagRelease for this binary upload.
19+ """Return the respective ISourcePackageRelease for this binary upload.
20
21- It inspect publication in the targeted DistroSeries and also the
22- ACCEPTED queue for sources matching stored
23- (source_name, source_version).
24+ It inspect publication in the targeted DistroSeries.
25
26 It raises UploadError if the source was not found.
27
28@@ -793,43 +791,24 @@
29 mixed_uploads (source + binary) we do not have the source stored
30 in DB yet (see verifySourcepackagerelease).
31 """
32+ assert self.source_name is not None
33+ assert self.source_version is not None
34 distroseries = self.policy.distroseries
35 spphs = distroseries.getPublishedSources(
36 self.source_name, version=self.source_version,
37 include_pending=True, archive=self.policy.archive)
38
39- sourcepackagerelease = None
40- if spphs:
41- # We know there's only going to be one release because
42- # version is unique.
43- assert spphs.count() == 1, "Duplicated ancestry"
44- sourcepackagerelease = spphs[0].sourcepackagerelease
45- else:
46- # XXX cprov 2006-08-09 bug=55774: Building from ACCEPTED is
47- # special condition, not really used in production. We should
48- # remove the support for this use case.
49- self.logger.debug(
50- "No source published, checking the ACCEPTED queue")
51-
52- queue_candidates = distroseries.getQueueItems(
53- status=PackageUploadStatus.ACCEPTED,
54- name=self.source_name, version=self.source_version,
55- archive=self.policy.archive, exact_match=True)
56-
57- for queue_item in queue_candidates:
58- if queue_item.sources.count():
59- sourcepackagerelease = queue_item.sourcepackagerelease
60-
61- if sourcepackagerelease is None:
62- # At this point, we can't really do much more to try
63- # building this package. If we look in the NEW queue it is
64- # possible that multiple versions of the package exist there
65- # and we know how bad that can be. Time to give up!
66+ if spphs.count() == 0:
67 raise UploadError(
68 "Unable to find source package %s/%s in %s" % (
69 self.source_name, self.source_version, distroseries.name))
70
71- return sourcepackagerelease
72+ # There can only be one matching published source package.
73+ published_spphs = [
74+ spph for spph in spphs
75+ if spph.status == PackagePublishingStatus.PUBLISHED]
76+ assert len(published_spphs) <= 1, "Duplicated ancestry"
77+ return spphs[0].sourcepackagerelease
78
79 def verifySourcePackageRelease(self, sourcepackagerelease):
80 """Check if the given ISourcePackageRelease matches the context."""
81
82=== modified file 'lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt'
83--- lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt 2009-04-17 10:32:16 +0000
84+++ lib/lp/archiveuploader/tests/nascentupload-epoch-handling.txt 2010-10-14 18:06:51 +0000
85@@ -208,6 +208,14 @@
86 >>> bar_spr.version
87 u'1:1.0-9'
88
89+ >>> from lp.registry.interfaces.pocket import PackagePublishingPocket
90+ >>> from lp.soyuz.interfaces.publishing import IPublishingSet
91+ >>> getUtility(IPublishingSet).newSourcePublication(
92+ ... bar_src_upload.policy.distro.main_archive, bar_spr,
93+ ... bar_src_upload.policy.distroseries, bar_spr.component,
94+ ... bar_spr.section, PackagePublishingPocket.RELEASE)
95+ <SourcePackagePublishingHistory at ...>
96+
97 Let's accept the source and claim 'build from accepted' to process the
98 respective binary:
99
100@@ -217,9 +225,6 @@
101 >>> bar_src_queue.status.name
102 'ACCEPTED'
103
104- >>> from canonical.launchpad.ftests import syncUpdate
105- >>> syncUpdate(bar_src_queue)
106-
107 For a binary upload we expect the same, a BinaryPackageRelease
108 'version' that includes 'epoch':
109
110
111=== modified file 'lib/lp/archiveuploader/tests/nascentupload.txt'
112--- lib/lp/archiveuploader/tests/nascentupload.txt 2010-10-06 11:46:51 +0000
113+++ lib/lp/archiveuploader/tests/nascentupload.txt 2010-10-14 18:06:51 +0000
114@@ -484,86 +484,6 @@
115 1
116
117
118-=== Building From ACCEPTED queue ===
119-
120-XXX cprov 20060728: Building from ACCEPTED is special condition, not
121-really used in production. We should remove the support for this use
122-case, see further info in bug #55774.
123-
124-Next we send in the binaries, since the source should be in ACCEPTED the
125-binary should go straight there too. Note that we are not specifying
126-any build, so it should be created appropriately, it is what happens
127-with staged security uploads:
128-
129-XXX cprov 20070404: we are using a modified sync policy because we
130-need unsigned changes and binaries uploads (same as security, but also
131-accepts non-security uploads)
132-
133- >>> from lp.archiveuploader.uploadpolicy import ArchiveUploadType
134- >>> modified_sync_policy = getPolicy(
135- ... name='sync', distro='ubuntu', distroseries='hoary')
136- >>> modified_sync_policy.accepted_type = ArchiveUploadType.BINARY_ONLY
137-
138- >>> ed_bin = NascentUpload.from_changesfile_path(
139- ... datadir('split-upload-test/ed_0.2-20_i386.changes'),
140- ... modified_sync_policy, mock_logger_quiet)
141-
142- >>> ed_bin.process()
143- >>> ed_bin.is_rejected
144- False
145-
146- >>> success = ed_bin.do_accept()
147-
148- >>> ed_bin.queue_root.status.name
149- 'NEW'
150-
151-A build was created to represent the relationship between ed_src
152-(waiting in ACCEPTED queue) and the just uploaded ed_bin:
153-
154- >>> ed_build = ed_bin.queue_root.builds[0].build
155-
156- >>> ed_spr.id == ed_build.source_package_release.id
157- True
158-
159- >>> ed_build.title
160- u'i386 build of ed 0.2-20 in ubuntu hoary RELEASE'
161-
162- >>> ed_build.status.name
163- 'FULLYBUILT'
164-
165-Binary control file attributes are stored as text in the
166-BinaryPackageRelease record.
167-
168- >>> ed_bpr = ed_build.binarypackages[0]
169-
170- >>> ed_bpr.depends
171- u'libc6 (>= 2.6-1)'
172-
173- >>> ed_bpr.suggests
174- u'emacs'
175-
176- >>> ed_bpr.conflicts
177- u'vi'
178-
179- >>> ed_bpr.replaces
180- u'vim'
181-
182- >>> ed_bpr.provides
183- u'ed'
184-
185- >>> ed_bpr.essential
186- False
187-
188- >>> ed_bpr.pre_depends
189- u'dpkg'
190-
191- >>> ed_bpr.enhances
192- u'bash'
193-
194- >>> ed_bpr.breaks
195- u'emacs'
196-
197-
198 === Staged Source and Binary upload with multiple binaries ===
199
200 As we could see both, sources and binaries, get into Launchpad via
201@@ -613,12 +533,18 @@
202 >>> multibar_src_queue.status.name
203 'ACCEPTED'
204
205-We can just assume the source was published by step 3 and 4 for
206-simplicity and claim 'build from ACCEPTED' feature.
207+Then the source gets accepted and published, step 3 and 4:
208+
209+ >>> from lp.registry.interfaces.pocket import PackagePublishingPocket
210+ >>> from lp.soyuz.interfaces.publishing import IPublishingSet
211+ >>> getUtility(IPublishingSet).newSourcePublication(
212+ ... multibar_src_queue.archive, multibar_spr,
213+ ... sync_policy.distroseries, multibar_spr.component,
214+ ... multibar_spr.section, PackagePublishingPocket.RELEASE)
215+ <SourcePackagePublishingHistory at ...>
216
217 Build creation is done based on the SourcePackageRelease object, step 5:
218
219- >>> from lp.registry.interfaces.pocket import PackagePublishingPocket
220 >>> multibar_build = multibar_spr.createBuild(
221 ... hoary['i386'], PackagePublishingPocket.RELEASE,
222 ... multibar_src_queue.archive)
223@@ -636,8 +562,8 @@
224 and the collection of DEB files produced.
225
226 At this point slave-scanner moves the upload to the appropriate path
227-(/srv/launchpad.net/builddmaster) and invokes process-upload.py with
228-the 'buildd' upload policy and the build record id.
229+(/srv/launchpad.net/builddmaster). A cron job invokes process-upload.py
230+with the 'buildd' upload policy and processes all files in that directory.
231
232 >>> buildd_policy = getPolicy(
233 ... name='buildd', distro='ubuntu', distroseries='hoary')
234
235=== modified file 'lib/lp/archiveuploader/tests/test_nascentuploadfile.py'
236--- lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-10-06 11:46:51 +0000
237+++ lib/lp/archiveuploader/tests/test_nascentuploadfile.py 2010-10-14 18:06:51 +0000
238@@ -25,7 +25,10 @@
239 from lp.registry.interfaces.pocket import PackagePublishingPocket
240 from lp.archiveuploader.tests import AbsolutelyAnythingGoesUploadPolicy
241 from lp.buildmaster.enums import BuildStatus
242-from lp.soyuz.enums import PackageUploadCustomFormat
243+from lp.soyuz.enums import (
244+ PackageUploadCustomFormat,
245+ PackagePublishingStatus,
246+ )
247 from lp.testing import TestCaseWithFactory
248
249
250@@ -387,3 +390,97 @@
251 "foo_0.42_i386.deb", "main/python", "unknown", "mypkg", "0.42",
252 None)
253 self.assertRaises(UploadError, uploadfile.checkBuild, build)
254+
255+ def test_findSourcePackageRelease(self):
256+ # findSourcePackageRelease finds the matching SourcePackageRelease.
257+ das = self.factory.makeDistroArchSeries(
258+ distroseries=self.policy.distroseries, architecturetag="i386")
259+ build = self.factory.makeBinaryPackageBuild(
260+ distroarchseries=das,
261+ archive=self.policy.archive)
262+ uploadfile = self.createDebBinaryUploadFile(
263+ "foo_0.42_i386.deb", "main/python", "unknown", "mypkg", "0.42",
264+ None)
265+ spph = self.factory.makeSourcePackagePublishingHistory(
266+ sourcepackagename=self.factory.makeSourcePackageName("foo"),
267+ distroseries=self.policy.distroseries,
268+ version="0.42", archive=self.policy.archive)
269+ control = self.getBaseControl()
270+ control["Source"] = "foo"
271+ uploadfile.parseControl(control)
272+ self.assertEquals(
273+ spph.sourcepackagerelease, uploadfile.findSourcePackageRelease())
274+
275+ def test_findSourcePackageRelease_no_spph(self):
276+ # findSourcePackageRelease raises UploadError if there is no
277+ # SourcePackageRelease.
278+ das = self.factory.makeDistroArchSeries(
279+ distroseries=self.policy.distroseries, architecturetag="i386")
280+ build = self.factory.makeBinaryPackageBuild(
281+ distroarchseries=das,
282+ archive=self.policy.archive)
283+ uploadfile = self.createDebBinaryUploadFile(
284+ "foo_0.42_i386.deb", "main/python", "unknown", "mypkg", "0.42",
285+ None)
286+ control = self.getBaseControl()
287+ control["Source"] = "foo"
288+ uploadfile.parseControl(control)
289+ self.assertRaises(UploadError, uploadfile.findSourcePackageRelease)
290+
291+ def test_findSourcePackageRelease_multiple_sprs(self):
292+ # findSourcePackageRelease finds the last uploaded
293+ # SourcePackageRelease and can deal with multiple pending source
294+ # package releases.
295+ das = self.factory.makeDistroArchSeries(
296+ distroseries=self.policy.distroseries, architecturetag="i386")
297+ build = self.factory.makeBinaryPackageBuild(
298+ distroarchseries=das,
299+ archive=self.policy.archive)
300+ uploadfile = self.createDebBinaryUploadFile(
301+ "foo_0.42_i386.deb", "main/python", "unknown", "mypkg", "0.42",
302+ None)
303+ spn = self.factory.makeSourcePackageName("foo")
304+ spph1 = self.factory.makeSourcePackagePublishingHistory(
305+ sourcepackagename=spn,
306+ distroseries=self.policy.distroseries,
307+ version="0.42", archive=self.policy.archive,
308+ status=PackagePublishingStatus.PUBLISHED)
309+ spph2 = self.factory.makeSourcePackagePublishingHistory(
310+ sourcepackagename=spn,
311+ distroseries=self.policy.distroseries,
312+ version="0.42", archive=self.policy.archive,
313+ status=PackagePublishingStatus.PENDING)
314+ control = self.getBaseControl()
315+ control["Source"] = "foo"
316+ uploadfile.parseControl(control)
317+ self.assertEquals(
318+ spph2.sourcepackagerelease, uploadfile.findSourcePackageRelease())
319+
320+ def test_findSourcePackageRelease_duplicated_ancestry(self):
321+ # findSourcePackageRelease errors out if there are multiple
322+ # published SourcePackageReleases, as this should never
323+ # be possible.
324+ das = self.factory.makeDistroArchSeries(
325+ distroseries=self.policy.distroseries, architecturetag="i386")
326+ build = self.factory.makeBinaryPackageBuild(
327+ distroarchseries=das,
328+ archive=self.policy.archive)
329+ uploadfile = self.createDebBinaryUploadFile(
330+ "foo_0.42_i386.deb", "main/python", "unknown", "mypkg", "0.42",
331+ None)
332+ spn = self.factory.makeSourcePackageName("foo")
333+ spph1 = self.factory.makeSourcePackagePublishingHistory(
334+ sourcepackagename=spn,
335+ distroseries=self.policy.distroseries,
336+ version="0.42", archive=self.policy.archive,
337+ status=PackagePublishingStatus.PUBLISHED)
338+ spph2 = self.factory.makeSourcePackagePublishingHistory(
339+ sourcepackagename=spn,
340+ distroseries=self.policy.distroseries,
341+ version="0.42", archive=self.policy.archive,
342+ status=PackagePublishingStatus.PUBLISHED)
343+ control = self.getBaseControl()
344+ control["Source"] = "foo"
345+ uploadfile.parseControl(control)
346+ self.assertRaises(
347+ AssertionError, uploadfile.findSourcePackageRelease)