Merge lp:~michael.nelson/launchpad/530180-partner-permissions into lp:launchpad

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~michael.nelson/launchpad/530180-partner-permissions
Merge into: lp:launchpad
Diff against target: 473 lines (+257/-51)
8 files modified
lib/canonical/launchpad/security.py (+2/-1)
lib/lp/soyuz/browser/queue.py (+1/-1)
lib/lp/soyuz/browser/tests/test_queue.py (+191/-0)
lib/lp/soyuz/doc/archivepermission.txt (+3/-2)
lib/lp/soyuz/interfaces/archivepermission.py (+2/-1)
lib/lp/soyuz/model/archivepermission.py (+12/-7)
lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt (+42/-35)
lib/lp/soyuz/tests/test_publishing.py (+4/-4)
To merge this branch: bzr merge lp:~michael.nelson/launchpad/530180-partner-permissions
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Review via email: mp+20947@code.launchpad.net

Commit message

If a person has permission to administer the queue page for one of the main archives then the view will allow them to post (while still checking individual queue items).

Description of the change

Summary
=======

This branch ensures that if a person has permission to administer the queue for one of the main archives for a distro, then they the /distro/series/+queue page will allow them to post.

Previously the security adapter checked only for permissions on the primary archive. The provided unit test show that now it is possible to have permission for the partner archive only, and be able to post to the view.

Note: the view still checks the permission on each individual item, also shown in the new unit tests.

To test:
bin/test -vv -t doc/archivepermission.txt -t xx-queue-pages.txt -t TestAcceptQueueUploads

The tests were originally written to demonstrate bug 530180, but as identified there, they actually showed that the original problem on the bug was related to incorrect permissions.

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) wrote :

Hi Michael,

You need to change the copyright notice in your unit test to read 2010 instead of 2009 (and if you'd do the templates as well I'd be grateful).

Other than that this branch looks fine. r=me.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/security.py'
--- lib/canonical/launchpad/security.py 2010-03-09 08:24:53 +0000
+++ lib/canonical/launchpad/security.py 2010-03-09 15:41:38 +0000
@@ -1360,7 +1360,8 @@
13601360
1361 permission_set = getUtility(IArchivePermissionSet)1361 permission_set = getUtility(IArchivePermissionSet)
1362 permissions = permission_set.componentsForQueueAdmin(1362 permissions = permission_set.componentsForQueueAdmin(
1363 self.obj.distroseries.main_archive, user.person)1363 self.obj.distroseries.distribution.all_distro_archives,
1364 user.person)
1364 return permissions.count() > 01365 return permissions.count() > 0
13651366
13661367
13671368
=== modified file 'lib/lp/soyuz/browser/queue.py'
--- lib/lp/soyuz/browser/queue.py 2009-07-19 04:41:14 +0000
+++ lib/lp/soyuz/browser/queue.py 2010-03-09 15:41:38 +0000
@@ -283,7 +283,7 @@
283 self.error = "Invalid component: %s" % component_override283 self.error = "Invalid component: %s" % component_override
284 return284 return
285285
286 # Get a list of components that the user has rights to accept and286 # Get a list of components for which the user has rights to
287 # override to or from.287 # override to or from.
288 permission_set = getUtility(IArchivePermissionSet)288 permission_set = getUtility(IArchivePermissionSet)
289 permissions = permission_set.componentsForQueueAdmin(289 permissions = permission_set.componentsForQueueAdmin(
290290
=== added file 'lib/lp/soyuz/browser/tests/test_queue.py'
--- lib/lp/soyuz/browser/tests/test_queue.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/browser/tests/test_queue.py 2010-03-09 15:41:38 +0000
@@ -0,0 +1,191 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Unit tests for QueueItemsView."""
5
6__metaclass__ = type
7__all__ = [
8 'TestAcceptPartnerArchive',
9 'test_suite',
10 ]
11
12import transaction
13import unittest
14from zope.component import getUtility, queryMultiAdapter
15
16from canonical.launchpad.webapp.servers import LaunchpadTestRequest
17from canonical.testing import LaunchpadFunctionalLayer
18
19from lp.archiveuploader.tests import datadir
20from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
21from lp.soyuz.interfaces.queue import IPackageUploadSet, PackageUploadStatus
22from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
23from lp.testing import login, logout, TestCaseWithFactory
24
25
26class TestAcceptQueueUploads(TestCaseWithFactory):
27 """Uploads for the partner archive can be accepted with the relevant
28 permissions.
29 """
30
31 layer = LaunchpadFunctionalLayer
32
33 def setUp(self):
34 """Create two new uploads in the new state and a person with
35 permission to upload to the partner archive."""
36 super(TestAcceptQueueUploads, self).setUp()
37 login('admin@canonical.com')
38 self.test_publisher = SoyuzTestPublisher()
39 self.test_publisher.prepareBreezyAutotest()
40 distribution = self.test_publisher.distroseries.distribution
41 self.main_archive = distribution.getArchiveByComponent('main')
42 self.partner_archive = distribution.getArchiveByComponent('partner')
43
44 # Get some sample changes file content for the new uploads.
45 changes_file = open(
46 datadir('suite/bar_1.0-1/bar_1.0-1_source.changes'))
47 changes_file_content = changes_file.read()
48 changes_file.close()
49
50 self.partner_spr = self.test_publisher.getPubSource(
51 sourcename='partner-upload', spr_only=True,
52 component='partner', changes_file_content=changes_file_content,
53 archive=self.partner_archive)
54 self.partner_spr.package_upload.setNew()
55 self.main_spr = self.test_publisher.getPubSource(
56 sourcename='main-upload', spr_only=True,
57 component='main', changes_file_content=changes_file_content)
58 self.main_spr.package_upload.setNew()
59
60 # Define the form that will be used to post to the view.
61 self.form = {
62 'queue_state': PackageUploadStatus.NEW.value,
63 'Accept': 'Accept',
64 }
65
66 # Create a user with queue admin rights for main, and a separate
67 # user with queue admin rights for partner (on the partner
68 # archive).
69 self.main_queue_admin = self.factory.makePerson(
70 email='main-queue@example.org')
71 getUtility(IArchivePermissionSet).newQueueAdmin(
72 distribution.getArchiveByComponent('main'),
73 self.main_queue_admin, self.main_spr.component)
74 self.partner_queue_admin = self.factory.makePerson(
75 email='partner-queue@example.org')
76 getUtility(IArchivePermissionSet).newQueueAdmin(
77 distribution.getArchiveByComponent('partner'),
78 self.partner_queue_admin, self.partner_spr.component)
79
80
81 # We need to commit to ensure the changes file exists in the
82 # librarian.
83 transaction.commit()
84 logout()
85
86 def setupQueueView(self, request):
87 """A helper to create and setup the view for testing."""
88 view = queryMultiAdapter(
89 (self.test_publisher.distroseries, request), name="+queue")
90 view.setupQueueList()
91 view.performQueueAction()
92 return view
93
94 def test_main_admin_can_accept_main_upload(self):
95 # A person with queue admin access for main
96 # can accept uploads to the main archive.
97 login('main-queue@example.org')
98 self.assertTrue(
99 self.main_archive.canAdministerQueue(
100 self.main_queue_admin, self.main_spr.component))
101
102 package_upload_id = self.main_spr.package_upload.id
103 self.form['QUEUE_ID'] = [package_upload_id]
104 request = LaunchpadTestRequest(form=self.form)
105 request.method = 'POST'
106 view = self.setupQueueView(request)
107
108 self.assertEquals(
109 'DONE',
110 getUtility(IPackageUploadSet).get(package_upload_id).status.name)
111
112 def test_main_admin_cannot_accept_partner_upload(self):
113 # A person with queue admin access for main cannot necessarily
114 # accept uploads to partner.
115 login('main-queue@example.org')
116 self.assertFalse(
117 self.partner_archive.canAdministerQueue(
118 self.main_queue_admin, self.partner_spr.component))
119
120 package_upload_id = self.partner_spr.package_upload.id
121 self.form['QUEUE_ID'] = [package_upload_id]
122 request = LaunchpadTestRequest(form=self.form)
123 request.method = 'POST'
124 view = self.setupQueueView(request)
125
126 self.assertEquals(
127 "FAILED: partner-upload (You have no rights to accept "
128 "component(s) 'partner')",
129 view.request.response.notifications[0].message)
130 self.assertEquals(
131 'NEW',
132 getUtility(IPackageUploadSet).get(package_upload_id).status.name)
133
134 def test_admin_can_accept_partner_upload(self):
135 # An admin can always accept packages, even for the
136 # partner archive (note, this is *not* an archive admin).
137 login('admin@canonical.com')
138
139 package_upload_id = self.partner_spr.package_upload.id
140 self.form['QUEUE_ID'] = [package_upload_id]
141 request = LaunchpadTestRequest(form=self.form)
142 request.method = 'POST'
143 view = self.setupQueueView(request)
144
145 self.assertEquals(
146 'DONE',
147 getUtility(IPackageUploadSet).get(package_upload_id).status.name)
148
149 def test_partner_admin_can_accept_partner_upload(self):
150 # A person with queue admin access for partner
151 # can accept uploads to the partner archive.
152 login('partner-queue@example.org')
153 self.assertTrue(
154 self.partner_archive.canAdministerQueue(
155 self.partner_queue_admin, self.partner_spr.component))
156
157 package_upload_id = self.partner_spr.package_upload.id
158 self.form['QUEUE_ID'] = [package_upload_id]
159 request = LaunchpadTestRequest(form=self.form)
160 request.method = 'POST'
161 view = self.setupQueueView(request)
162
163 self.assertEquals(
164 'DONE',
165 getUtility(IPackageUploadSet).get(package_upload_id).status.name)
166
167 def test_partner_admin_cannot_accept_main_upload(self):
168 # A person with queue admin access for partner cannot necessarily
169 # accept uploads to main.
170 login('partner-queue@example.org')
171 self.assertFalse(
172 self.main_archive.canAdministerQueue(
173 self.partner_queue_admin, self.main_spr.component))
174
175 package_upload_id = self.main_spr.package_upload.id
176 self.form['QUEUE_ID'] = [package_upload_id]
177 request = LaunchpadTestRequest(form=self.form)
178 request.method = 'POST'
179 view = self.setupQueueView(request)
180
181 self.assertEquals(
182 "FAILED: main-upload (You have no rights to accept "
183 "component(s) 'main')",
184 view.request.response.notifications[0].message)
185 self.assertEquals(
186 'NEW',
187 getUtility(IPackageUploadSet).get(package_upload_id).status.name)
188
189def test_suite():
190 return unittest.TestLoader().loadTestsFromName(__name__)
191
0192
=== modified file 'lib/lp/soyuz/doc/archivepermission.txt'
--- lib/lp/soyuz/doc/archivepermission.txt 2009-12-24 01:41:54 +0000
+++ lib/lp/soyuz/doc/archivepermission.txt 2010-03-09 15:41:38 +0000
@@ -236,7 +236,8 @@
236236
237componentsForQueueAdmin() returns the ArchivePermission records for all237componentsForQueueAdmin() returns the ArchivePermission records for all
238the components that the supplied user has permission to administer in238the components that the supplied user has permission to administer in
239the distroseries queue.239the distroseries queue. It can be passed a single archive or an
240enumeration of archives.
240241
241 >>> name12 = getUtility(IPersonSet).getByName("name12")242 >>> name12 = getUtility(IPersonSet).getByName("name12")
242 >>> permissions = permission_set.componentsForQueueAdmin(243 >>> permissions = permission_set.componentsForQueueAdmin(
@@ -250,7 +251,7 @@
250251
251 >>> no_team = getUtility(IPersonSet).getByName("no-team-memberships")252 >>> no_team = getUtility(IPersonSet).getByName("no-team-memberships")
252 >>> permissions = permission_set.componentsForQueueAdmin(253 >>> permissions = permission_set.componentsForQueueAdmin(
253 ... ubuntu.main_archive, no_team)254 ... ubuntu.all_distro_archives, no_team)
254 >>> for permission in sorted(permissions, key=operator.attrgetter("id")):255 >>> for permission in sorted(permissions, key=operator.attrgetter("id")):
255 ... print permission.component.name256 ... print permission.component.name
256 universe257 universe
257258
=== modified file 'lib/lp/soyuz/interfaces/archivepermission.py'
--- lib/lp/soyuz/interfaces/archivepermission.py 2009-11-03 18:44:59 +0000
+++ lib/lp/soyuz/interfaces/archivepermission.py 2010-03-09 15:41:38 +0000
@@ -323,7 +323,8 @@
323 def componentsForQueueAdmin(archive, person):323 def componentsForQueueAdmin(archive, person):
324 """Return `ArchivePermission` for the person's queue admin components.324 """Return `ArchivePermission` for the person's queue admin components.
325325
326 :param archive: The context `IArchive` for the permission check.326 :param archive: The context `IArchive` for the permission check, or
327 an iterable of `IArchive`s.
327 :param person: An `IPerson` for whom you want to find out which328 :param person: An `IPerson` for whom you want to find out which
328 components he has access to.329 components he has access to.
329330
330331
=== modified file 'lib/lp/soyuz/model/archivepermission.py'
--- lib/lp/soyuz/model/archivepermission.py 2009-11-03 18:44:59 +0000
+++ lib/lp/soyuz/model/archivepermission.py 2010-03-09 15:41:38 +0000
@@ -23,7 +23,7 @@
23from canonical.database.sqlbase import sqlvalues, SQLBase23from canonical.database.sqlbase import sqlvalues, SQLBase
2424
25from lp.registry.interfaces.distribution import IDistributionSet25from lp.registry.interfaces.distribution import IDistributionSet
26from lp.soyuz.interfaces.archive import ComponentNotFound26from lp.soyuz.interfaces.archive import ComponentNotFound, IArchive
27from lp.soyuz.interfaces.archivepermission import (27from lp.soyuz.interfaces.archivepermission import (
28 ArchivePermissionType, IArchivePermission, IArchivePermissionSet,28 ArchivePermissionType, IArchivePermission, IArchivePermissionSet,
29 IArchiveUploader, IArchiveQueueAdmin)29 IArchiveUploader, IArchiveQueueAdmin)
@@ -92,7 +92,7 @@
92 def component_name(self):92 def component_name(self):
93 """See `IArchivePermission`"""93 """See `IArchivePermission`"""
94 if self.component:94 if self.component:
95 return self.component.name 95 return self.component.name
96 else:96 else:
97 return None97 return None
9898
@@ -189,17 +189,22 @@
189 TeamParticipation.team = ArchivePermission.person)189 TeamParticipation.team = ArchivePermission.person)
190 """ % sqlvalues(archive, person))190 """ % sqlvalues(archive, person))
191191
192 def _componentsFor(self, archive, person, permission_type):192 def _componentsFor(self, archives, person, permission_type):
193 """Helper function to get ArchivePermission objects."""193 """Helper function to get ArchivePermission objects."""
194 if IArchive.providedBy(archives):
195 archive_ids = [archives.id]
196 else:
197 archive_ids = [archive.id for archive in archives]
198
194 return ArchivePermission.select("""199 return ArchivePermission.select("""
195 ArchivePermission.archive = %s AND200 ArchivePermission.archive IN %s AND
196 ArchivePermission.permission = %s AND201 ArchivePermission.permission = %s AND
197 ArchivePermission.component IS NOT NULL AND202 ArchivePermission.component IS NOT NULL AND
198 EXISTS (SELECT TeamParticipation.person203 EXISTS (SELECT TeamParticipation.person
199 FROM TeamParticipation204 FROM TeamParticipation
200 WHERE TeamParticipation.person = %s AND205 WHERE TeamParticipation.person = %s AND
201 TeamParticipation.team = ArchivePermission.person)206 TeamParticipation.team = ArchivePermission.person)
202 """ % sqlvalues(archive, permission_type, person),207 """ % sqlvalues(archive_ids, permission_type, person),
203 prejoins=["component"])208 prejoins=["component"])
204209
205 def componentsForUploader(self, archive, person):210 def componentsForUploader(self, archive, person):
@@ -504,7 +509,7 @@
504 # Query parameters for the first WHERE clause.509 # Query parameters for the first WHERE clause.
505 (archive.id, distroseries.id, sourcepackagename.id) +510 (archive.id, distroseries.id, sourcepackagename.id) +
506 # Query parameters for the second WHERE clause.511 # Query parameters for the second WHERE clause.
507 permission_params + archive_params + 512 permission_params + archive_params +
508 # Query parameters for the third WHERE clause.513 # Query parameters for the third WHERE clause.
509 permission_params + archive_params)514 permission_params + archive_params)
510515
@@ -521,7 +526,7 @@
521 THEN (526 THEN (
522 SELECT COUNT(ap.id)527 SELECT COUNT(ap.id)
523 FROM528 FROM
524 packagesetsources pss, archivepermission ap, packageset ps, 529 packagesetsources pss, archivepermission ap, packageset ps,
525 teamparticipation tp530 teamparticipation tp
526 WHERE531 WHERE
527 pss.sourcepackagename = %s532 pss.sourcepackagename = %s
528533
=== modified file 'lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt'
--- lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt 2009-07-16 00:31:36 +0000
+++ lib/lp/soyuz/stories/soyuz/xx-queue-pages.txt 2010-03-09 15:41:38 +0000
@@ -195,37 +195,33 @@
195195
196 >>> from zope.component import getUtility196 >>> from zope.component import getUtility
197 >>> from canonical.launchpad.ftests import login, logout197 >>> from canonical.launchpad.ftests import login, logout
198 >>> from canonical.launchpad.interfaces import (198 >>> from canonical.launchpad.interfaces import IDistributionSet
199 ... IDistributionSet, ILibraryFileAliasSet)199 >>> from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
200 >>> from canonical.launchpad.ftests import syncUpdate
201200
202 >>> login('foo.bar@canonical.com')201 >>> login('foo.bar@canonical.com')
203202
204 >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')203 >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu')
205 >>> fake_chroot = getUtility(ILibraryFileAliasSet)[1]204
206 >>> breezy_autotest = ubuntu.getSeries('breezy-autotest')205 >>> breezy_autotest = ubuntu.getSeries('breezy-autotest')
207 >>> new_chroot = breezy_autotest["i386"].addOrUpdateChroot(fake_chroot)206 >>> test_publisher = SoyuzTestPublisher()
208 >>> syncUpdate(new_chroot)207 >>> ignore = test_publisher.setUpDefaultDistroSeries(breezy_autotest)
209208 >>> test_publisher.addFakeChroots(distroseries=breezy_autotest)
210Upload a new "bar" source so we can accept it later. We need to login to209
211upload.210Upload a new "bar" source so we can accept it later.
212211
213 >>> from lp.archiveuploader.tests import (212 >>> from lp.archiveuploader.tests import datadir
214 ... datadir, getPolicy, mock_logger_quiet)213 >>> changes_file = open(
215 >>> from lp.archiveuploader.nascentupload import NascentUpload214 ... datadir('suite/bar_1.0-1/bar_1.0-1_source.changes'))
216215 >>> changes_file_content = changes_file.read()
217 >>> sync_policy = getPolicy(216 >>> changes_file.close()
218 ... name='sync', distro='ubuntu', distroseries='breezy-autotest')217
219 >>> bar_src = NascentUpload(218 >>> bar_src = test_publisher.getPubSource(
220 ... datadir('suite/bar_1.0-1/bar_1.0-1_source.changes'),219 ... sourcename='bar', distroseries=breezy_autotest, spr_only=True,
221 ... sync_policy, mock_logger_quiet)220 ... version='1.0-1', component='universe', section='devel',
222 >>> bar_src.process()221 ... changes_file_content=changes_file_content)
223 >>> bar_src.do_accept()222
224 True223 >>> bar_src.package_upload.setNew()
225 >>> bar_queue_id = str(bar_src.queue_root.id)224 >>> bar_queue_id = bar_src.package_upload.id
226
227 >>> import transaction
228 >>> transaction.commit()
229 >>> logout()225 >>> logout()
230226
231Swallow any email generated at the upload:227Swallow any email generated at the upload:
@@ -246,8 +242,18 @@
246242
247 >>> upload_manager_browser.open(243 >>> upload_manager_browser.open(
248 ... "http://localhost/ubuntu/breezy-autotest/+queue")244 ... "http://localhost/ubuntu/breezy-autotest/+queue")
245 >>> print_queue(upload_manager_browser.contents)
246 Package Version Component Section Priority Pocket When
247 bar (source) 1.0-1 universe devel low Release ...
248 netapplet...ddtp... - Release 2006-...
249 netapplet...dist... - Release 2006-...
250 alsa-utils (source) 1.0.9a-4... main base low Release 2006-...
251 netapplet (source) 0.99.6-1 main web low Release 2006-...
252 pmount (i386) 0.1-1 Release 2006-...
253 moz...irefox (i386) 0.9 Release 2006-...
254
249 >>> upload_manager_browser.getControl(255 >>> upload_manager_browser.getControl(
250 ... name="QUEUE_ID").value = [bar_queue_id]256 ... name="QUEUE_ID").value = [str(bar_queue_id)]
251 >>> upload_manager_browser.getControl(name="Accept").click()257 >>> upload_manager_browser.getControl(name="Accept").click()
252 >>> print_queue(upload_manager_browser.contents)258 >>> print_queue(upload_manager_browser.contents)
253 Package Version Component Section Priority Pocket When259 Package Version Component Section Priority Pocket When
@@ -258,22 +264,23 @@
258 pmount (i386) 0.1-1 Release 2006-...264 pmount (i386) 0.1-1 Release 2006-...
259 moz...irefox (i386) 0.9 Release 2006-...265 moz...irefox (i386) 0.9 Release 2006-...
260266
261Accepting queue items results in an email to the uploader and (usually) an267Accepting queue items results in an email to the uploader (and the changer
262email to the distroseries' announcement list (see268if it is someone other than the uploader) and (usually) an email to the
263nascentupload-announcements.txt).269distroseries' announcement list (see nascentupload-announcements.txt).
264270
265 >>> [notification, announcement] = pop_notifications()271 >>> [notification, announcement] = pop_notifications()
266 >>> notification['To']272 >>> print notification['To']
267 'Daniel Silverstone <daniel.silverstone@canonical.com>'273 Foo Bar <foo.bar@canonical.com>,
268 >>> announcement['To']274 Daniel Silverstone <daniel.silverstone@canonical.com>
269 'autotest_changes@ubuntu.com'275 >>> print announcement['To']
276 autotest_changes@ubuntu.com
270277
271Forcing a duplicated submission on a queue item is recognised. Here we278Forcing a duplicated submission on a queue item is recognised. Here we
272submit the same form again via a different browser instance, which simulates279submit the same form again via a different browser instance, which simulates
273a double post.280a double post.
274281
275 >>> duplicate_submission_browser.getControl(282 >>> duplicate_submission_browser.getControl(
276 ... name="QUEUE_ID").value = [bar_queue_id]283 ... name="QUEUE_ID").value = [str(bar_queue_id)]
277 >>> duplicate_submission_browser.getControl(name="Accept").click()284 >>> duplicate_submission_browser.getControl(name="Accept").click()
278 >>> for message in get_feedback_messages(285 >>> for message in get_feedback_messages(
279 ... duplicate_submission_browser.contents):286 ... duplicate_submission_browser.contents):
280287
=== modified file 'lib/lp/soyuz/tests/test_publishing.py'
--- lib/lp/soyuz/tests/test_publishing.py 2010-02-27 20:20:03 +0000
+++ lib/lp/soyuz/tests/test_publishing.py 2010-03-09 15:41:38 +0000
@@ -219,15 +219,15 @@
219 upload_status=upload_status)219 upload_status=upload_status)
220 package_upload.addSource(spr)220 package_upload.addSource(spr)
221221
222 if spr_only:
223 return spr
224
225 if filename is None:222 if filename is None:
226 filename = "%s_%s.dsc" % (sourcename, version)223 filename = "%s_%s.dsc" % (sourcename, version)
227 alias = self.addMockFile(224 alias = self.addMockFile(
228 filename, filecontent, restricted=archive.private)225 filename, filecontent, restricted=archive.private)
229 spr.addFile(alias)226 spr.addFile(alias)
230227
228 if spr_only:
229 return spr
230
231 if status == PackagePublishingStatus.PUBLISHED:231 if status == PackagePublishingStatus.PUBLISHED:
232 datepublished = UTC_NOW232 datepublished = UTC_NOW
233 else:233 else:
@@ -405,7 +405,7 @@
405 """File with given name fragment in directory tree starting at top."""405 """File with given name fragment in directory tree starting at top."""
406 for root, dirs, files in os.walk(top, topdown=False):406 for root, dirs, files in os.walk(top, topdown=False):
407 for name in files:407 for name in files:
408 if (name.endswith('.changes') and 408 if (name.endswith('.changes') and
409 name.find(name_fragment) > -1):409 name.find(name_fragment) > -1):
410 return os.path.join(root, name)410 return os.path.join(root, name)
411 return None411 return None