Merge lp:~cjwatson/launchpad/archive-dependencies-unittest into lp:launchpad
- archive-dependencies-unittest
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 18378 |
Proposed branch: | lp:~cjwatson/launchpad/archive-dependencies-unittest |
Merge into: | lp:launchpad |
Diff against target: |
1256 lines (+541/-643) 5 files modified
lib/lp/soyuz/adapters/tests/test_archivedependencies.py (+517/-0) lib/lp/soyuz/doc/archive-dependencies.txt (+0/-637) lib/lp/soyuz/interfaces/archive.py (+2/-2) lib/lp/soyuz/tests/test_archive.py (+14/-1) lib/lp/testing/factory.py (+8/-3) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/archive-dependencies-unittest |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+323129@code.launchpad.net |
Commit message
Convert archive-
Description of the change
I needed to do this to make it less painful to change get_sources_
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 | === added file 'lib/lp/soyuz/adapters/tests/test_archivedependencies.py' | |||
2 | --- lib/lp/soyuz/adapters/tests/test_archivedependencies.py 1970-01-01 00:00:00 +0000 | |||
3 | +++ lib/lp/soyuz/adapters/tests/test_archivedependencies.py 2017-04-25 11:47:06 +0000 | |||
4 | @@ -0,0 +1,517 @@ | |||
5 | 1 | # Copyright 2017 Canonical Ltd. This software is licensed under the | ||
6 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
7 | 3 | |||
8 | 4 | """Test archive dependencies.""" | ||
9 | 5 | |||
10 | 6 | from __future__ import absolute_import, print_function, unicode_literals | ||
11 | 7 | |||
12 | 8 | __metaclass__ = type | ||
13 | 9 | |||
14 | 10 | from testtools.matchers import StartsWith | ||
15 | 11 | import transaction | ||
16 | 12 | from zope.component import getUtility | ||
17 | 13 | |||
18 | 14 | from lp.registry.interfaces.distribution import IDistributionSet | ||
19 | 15 | from lp.registry.interfaces.pocket import PackagePublishingPocket | ||
20 | 16 | from lp.services.log.logger import BufferLogger | ||
21 | 17 | from lp.soyuz.adapters.archivedependencies import ( | ||
22 | 18 | default_component_dependency_name, | ||
23 | 19 | default_pocket_dependency, | ||
24 | 20 | get_components_for_context, | ||
25 | 21 | get_primary_current_component, | ||
26 | 22 | get_sources_list_for_building, | ||
27 | 23 | pocket_dependencies, | ||
28 | 24 | ) | ||
29 | 25 | from lp.soyuz.enums import PackagePublishingStatus | ||
30 | 26 | from lp.soyuz.interfaces.archive import IArchive | ||
31 | 27 | from lp.soyuz.interfaces.component import IComponentSet | ||
32 | 28 | from lp.soyuz.tests.test_publishing import SoyuzTestPublisher | ||
33 | 29 | from lp.testing import TestCaseWithFactory | ||
34 | 30 | from lp.testing.layers import ( | ||
35 | 31 | LaunchpadZopelessLayer, | ||
36 | 32 | ZopelessDatabaseLayer, | ||
37 | 33 | ) | ||
38 | 34 | |||
39 | 35 | |||
40 | 36 | class TestOgreModel(TestCaseWithFactory): | ||
41 | 37 | """Test ogre-model component handling. | ||
42 | 38 | |||
43 | 39 | The Ubuntu "ogre model" (cf. Shrek) ensures that build-dependencies are | ||
44 | 40 | consistent with the component in which the source is published. | ||
45 | 41 | """ | ||
46 | 42 | |||
47 | 43 | layer = ZopelessDatabaseLayer | ||
48 | 44 | |||
49 | 45 | def setUpComponents(self, distroseries, component_names): | ||
50 | 46 | for component_name in component_names: | ||
51 | 47 | component = getUtility(IComponentSet)[component_name] | ||
52 | 48 | self.factory.makeComponentSelection(distroseries, component) | ||
53 | 49 | |||
54 | 50 | def assertComponentMap(self, expected, distroseries, pocket): | ||
55 | 51 | for component_name, expected_components in expected.items(): | ||
56 | 52 | component = getUtility(IComponentSet)[component_name] | ||
57 | 53 | self.assertEqual( | ||
58 | 54 | expected_components, | ||
59 | 55 | get_components_for_context(component, distroseries, pocket)) | ||
60 | 56 | |||
61 | 57 | def test_strict_supported_component_dependencies(self): | ||
62 | 58 | # In strict-supported-component-dependencies mode, a source | ||
63 | 59 | # published in main is only allowed to build-depend on binaries also | ||
64 | 60 | # published in main, while a source published in universe is allowed | ||
65 | 61 | # to build-depend on main and universe. | ||
66 | 62 | distroseries = self.factory.makeDistroSeries() | ||
67 | 63 | expected = { | ||
68 | 64 | "main": ["main"], | ||
69 | 65 | "restricted": ["main", "restricted"], | ||
70 | 66 | "universe": ["main", "universe"], | ||
71 | 67 | "multiverse": ["main", "restricted", "universe", "multiverse"], | ||
72 | 68 | "partner": ["partner"], | ||
73 | 69 | } | ||
74 | 70 | self.setUpComponents(distroseries, expected.keys()) | ||
75 | 71 | self.assertComponentMap( | ||
76 | 72 | expected, distroseries, PackagePublishingPocket.RELEASE) | ||
77 | 73 | |||
78 | 74 | def test_lax_supported_component_dependencies(self): | ||
79 | 75 | # In lax-supported-component-dependencies mode, source packages in | ||
80 | 76 | # "supported" components (main and restricted) may additionally | ||
81 | 77 | # build-depend on binary packages in "unsupported" components | ||
82 | 78 | # (universe and multiverse). | ||
83 | 79 | distroseries = self.factory.makeDistroSeries() | ||
84 | 80 | distroseries.strict_supported_component_dependencies = False | ||
85 | 81 | expected = { | ||
86 | 82 | "main": ["main", "universe"], | ||
87 | 83 | "restricted": ["main", "restricted", "universe", "multiverse"], | ||
88 | 84 | "universe": ["main", "universe"], | ||
89 | 85 | "multiverse": ["main", "restricted", "universe", "multiverse"], | ||
90 | 86 | "partner": ["partner"], | ||
91 | 87 | } | ||
92 | 88 | self.setUpComponents(distroseries, expected.keys()) | ||
93 | 89 | self.assertComponentMap( | ||
94 | 90 | expected, distroseries, PackagePublishingPocket.RELEASE) | ||
95 | 91 | |||
96 | 92 | def test_backports(self): | ||
97 | 93 | # Source packages in the BACKPORTS pocket are allowed to | ||
98 | 94 | # build-depend on binary packages in any component. This avoids | ||
99 | 95 | # having to make potentially-invasive changes to accommodate | ||
100 | 96 | # backporting to stable series. | ||
101 | 97 | distroseries = self.factory.makeDistroSeries() | ||
102 | 98 | expected = { | ||
103 | 99 | "main": ["main", "restricted", "universe", "multiverse"], | ||
104 | 100 | "restricted": ["main", "restricted", "universe", "multiverse"], | ||
105 | 101 | "universe": ["main", "restricted", "universe", "multiverse"], | ||
106 | 102 | "multiverse": ["main", "restricted", "universe", "multiverse"], | ||
107 | 103 | "partner": ["main", "restricted", "universe", "multiverse"], | ||
108 | 104 | } | ||
109 | 105 | self.setUpComponents(distroseries, expected.keys()) | ||
110 | 106 | self.assertComponentMap( | ||
111 | 107 | expected, distroseries, PackagePublishingPocket.BACKPORTS) | ||
112 | 108 | |||
113 | 109 | |||
114 | 110 | class TestSourcesList(TestCaseWithFactory): | ||
115 | 111 | """Test sources.list contents for building, and related mechanisms.""" | ||
116 | 112 | |||
117 | 113 | layer = LaunchpadZopelessLayer | ||
118 | 114 | |||
119 | 115 | ubuntu_components = [ | ||
120 | 116 | "main", "restricted", "universe", "multiverse", "partner"] | ||
121 | 117 | |||
122 | 118 | def setUp(self): | ||
123 | 119 | super(TestSourcesList, self).setUp() | ||
124 | 120 | self.publisher = SoyuzTestPublisher() | ||
125 | 121 | self.ubuntu = getUtility(IDistributionSet).getByName("ubuntu") | ||
126 | 122 | self.hoary = self.ubuntu.getSeries("hoary") | ||
127 | 123 | self.publisher.addFakeChroots(self.hoary) | ||
128 | 124 | self.publisher.setUpDefaultDistroSeries(self.hoary) | ||
129 | 125 | for component_name in self.ubuntu_components: | ||
130 | 126 | component = getUtility(IComponentSet)[component_name] | ||
131 | 127 | if component not in self.hoary.components: | ||
132 | 128 | self.factory.makeComponentSelection(self.hoary, component) | ||
133 | 129 | |||
134 | 130 | def test_defaults(self): | ||
135 | 131 | # Non-primary archives by default use the Release, Security and | ||
136 | 132 | # Updates pockets from the primary archive, and all its available | ||
137 | 133 | # components. | ||
138 | 134 | self.assertEqual( | ||
139 | 135 | PackagePublishingPocket.UPDATES, default_pocket_dependency) | ||
140 | 136 | self.assertEqual("multiverse", default_component_dependency_name) | ||
141 | 137 | self.assertEqual( | ||
142 | 138 | (PackagePublishingPocket.RELEASE, | ||
143 | 139 | PackagePublishingPocket.SECURITY, | ||
144 | 140 | PackagePublishingPocket.UPDATES), | ||
145 | 141 | pocket_dependencies[default_pocket_dependency]) | ||
146 | 142 | |||
147 | 143 | def makeArchive(self, publish_binary=False, **kwargs): | ||
148 | 144 | archive = self.factory.makeArchive(distribution=self.ubuntu, **kwargs) | ||
149 | 145 | if publish_binary: | ||
150 | 146 | self.publisher.getPubBinaries( | ||
151 | 147 | archive=archive, status=PackagePublishingStatus.PUBLISHED) | ||
152 | 148 | return archive | ||
153 | 149 | |||
154 | 150 | def makeBuild(self, **kwargs): | ||
155 | 151 | pub_source = self.publisher.getPubSource(**kwargs) | ||
156 | 152 | [build] = pub_source.createMissingBuilds() | ||
157 | 153 | return build | ||
158 | 154 | |||
159 | 155 | def assertPrimaryCurrentComponent(self, expected, build): | ||
160 | 156 | self.assertEqual( | ||
161 | 157 | expected, | ||
162 | 158 | get_primary_current_component( | ||
163 | 159 | build.archive, build.distro_series, | ||
164 | 160 | build.source_package_release.name).name) | ||
165 | 161 | |||
166 | 162 | def assertSourcesList(self, expected, build, **kwargs): | ||
167 | 163 | expected_lines = [] | ||
168 | 164 | for archive_or_prefix, suffixes in expected: | ||
169 | 165 | if IArchive.providedBy(archive_or_prefix): | ||
170 | 166 | prefix = "deb %s " % archive_or_prefix.archive_url | ||
171 | 167 | else: | ||
172 | 168 | prefix = archive_or_prefix + " " | ||
173 | 169 | expected_lines.extend([prefix + suffix for suffix in suffixes]) | ||
174 | 170 | sources_list = get_sources_list_for_building( | ||
175 | 171 | build, build.distro_arch_series, build.source_package_release.name, | ||
176 | 172 | **kwargs) | ||
177 | 173 | self.assertEqual(expected_lines, sources_list) | ||
178 | 174 | |||
179 | 175 | def test_ppa_with_no_binaries(self): | ||
180 | 176 | # If there are no published binaries in a PPA, only its primary | ||
181 | 177 | # archive dependencies need to be considered. | ||
182 | 178 | ppa = self.makeArchive() | ||
183 | 179 | build = self.makeBuild(archive=ppa) | ||
184 | 180 | self.assertEqual( | ||
185 | 181 | 0, ppa.getAllPublishedBinaries( | ||
186 | 182 | distroarchseries=build.distro_arch_series, | ||
187 | 183 | status=PackagePublishingStatus.PUBLISHED).count()) | ||
188 | 184 | self.assertSourcesList( | ||
189 | 185 | [(self.ubuntu.main_archive, [ | ||
190 | 186 | "hoary main restricted universe multiverse", | ||
191 | 187 | "hoary-security main restricted universe multiverse", | ||
192 | 188 | "hoary-updates main restricted universe multiverse", | ||
193 | 189 | ]), | ||
194 | 190 | ], build) | ||
195 | 191 | |||
196 | 192 | def test_ppa_with_binaries(self): | ||
197 | 193 | # If there are binaries published in a PPA, then the PPA is | ||
198 | 194 | # considered as well as its primary dependencies. | ||
199 | 195 | ppa = self.makeArchive(publish_binary=True) | ||
200 | 196 | build = self.makeBuild(archive=ppa) | ||
201 | 197 | self.assertSourcesList( | ||
202 | 198 | [(ppa, ["hoary main"]), | ||
203 | 199 | (self.ubuntu.main_archive, [ | ||
204 | 200 | "hoary main restricted universe multiverse", | ||
205 | 201 | "hoary-security main restricted universe multiverse", | ||
206 | 202 | "hoary-updates main restricted universe multiverse", | ||
207 | 203 | ]), | ||
208 | 204 | ], build) | ||
209 | 205 | |||
210 | 206 | def test_dependent_ppa_with_no_binaries(self): | ||
211 | 207 | # A depended-upon PPA is not considered if it has no published | ||
212 | 208 | # binaries. | ||
213 | 209 | lower_ppa = self.makeArchive() | ||
214 | 210 | upper_ppa = self.makeArchive(publish_binary=True) | ||
215 | 211 | upper_ppa.addArchiveDependency( | ||
216 | 212 | lower_ppa, PackagePublishingPocket.RELEASE, | ||
217 | 213 | getUtility(IComponentSet)["main"]) | ||
218 | 214 | build = self.makeBuild(archive=upper_ppa) | ||
219 | 215 | self.assertSourcesList( | ||
220 | 216 | [(upper_ppa, ["hoary main"]), | ||
221 | 217 | (self.ubuntu.main_archive, [ | ||
222 | 218 | "hoary main restricted universe multiverse", | ||
223 | 219 | "hoary-security main restricted universe multiverse", | ||
224 | 220 | "hoary-updates main restricted universe multiverse", | ||
225 | 221 | ]), | ||
226 | 222 | ], build) | ||
227 | 223 | |||
228 | 224 | def test_dependent_ppa_with_binaries(self): | ||
229 | 225 | # A depended-upon PPA is considered if it has published binaries. | ||
230 | 226 | lower_ppa = self.makeArchive(publish_binary=True) | ||
231 | 227 | upper_ppa = self.makeArchive(publish_binary=True) | ||
232 | 228 | upper_ppa.addArchiveDependency( | ||
233 | 229 | lower_ppa, PackagePublishingPocket.RELEASE, | ||
234 | 230 | getUtility(IComponentSet)["main"]) | ||
235 | 231 | build = self.makeBuild(archive=upper_ppa) | ||
236 | 232 | self.assertSourcesList( | ||
237 | 233 | [(upper_ppa, ["hoary main"]), | ||
238 | 234 | (lower_ppa, ["hoary main"]), | ||
239 | 235 | (self.ubuntu.main_archive, [ | ||
240 | 236 | "hoary main restricted universe multiverse", | ||
241 | 237 | "hoary-security main restricted universe multiverse", | ||
242 | 238 | "hoary-updates main restricted universe multiverse", | ||
243 | 239 | ]), | ||
244 | 240 | ], build) | ||
245 | 241 | |||
246 | 242 | def test_lax_supported_component_dependencies(self): | ||
247 | 243 | # Dependencies for series with | ||
248 | 244 | # strict_supported_component_dependencies=False are reasonable. | ||
249 | 245 | # PPAs only have the "main" component. | ||
250 | 246 | lower_ppa = self.makeArchive(publish_binary=True) | ||
251 | 247 | upper_ppa = self.makeArchive(publish_binary=True) | ||
252 | 248 | upper_ppa.addArchiveDependency( | ||
253 | 249 | lower_ppa, PackagePublishingPocket.RELEASE, | ||
254 | 250 | getUtility(IComponentSet)["main"]) | ||
255 | 251 | upper_ppa.addArchiveDependency( | ||
256 | 252 | self.ubuntu.main_archive, PackagePublishingPocket.UPDATES, | ||
257 | 253 | getUtility(IComponentSet)["restricted"]) | ||
258 | 254 | build = self.makeBuild(archive=upper_ppa) | ||
259 | 255 | self.assertSourcesList( | ||
260 | 256 | [(upper_ppa, ["hoary main"]), | ||
261 | 257 | (lower_ppa, ["hoary main"]), | ||
262 | 258 | (self.ubuntu.main_archive, [ | ||
263 | 259 | "hoary main restricted", | ||
264 | 260 | "hoary-security main restricted", | ||
265 | 261 | "hoary-updates main restricted", | ||
266 | 262 | ]), | ||
267 | 263 | ], build) | ||
268 | 264 | self.hoary.strict_supported_component_dependencies = False | ||
269 | 265 | transaction.commit() | ||
270 | 266 | self.assertSourcesList( | ||
271 | 267 | [(upper_ppa, ["hoary main"]), | ||
272 | 268 | (lower_ppa, ["hoary main"]), | ||
273 | 269 | (self.ubuntu.main_archive, [ | ||
274 | 270 | "hoary main restricted universe multiverse", | ||
275 | 271 | "hoary-security main restricted universe multiverse", | ||
276 | 272 | "hoary-updates main restricted universe multiverse", | ||
277 | 273 | ]), | ||
278 | 274 | ], build) | ||
279 | 275 | |||
280 | 276 | def test_no_op_primary_archive_dependency(self): | ||
281 | 277 | # Overriding the default primary archive dependencies with exactly | ||
282 | 278 | # the same values has no effect. | ||
283 | 279 | ppa = self.makeArchive() | ||
284 | 280 | ppa.addArchiveDependency( | ||
285 | 281 | self.ubuntu.main_archive, PackagePublishingPocket.UPDATES, | ||
286 | 282 | getUtility(IComponentSet)["multiverse"]) | ||
287 | 283 | build = self.makeBuild(archive=ppa) | ||
288 | 284 | self.assertSourcesList( | ||
289 | 285 | [(self.ubuntu.main_archive, [ | ||
290 | 286 | "hoary main restricted universe multiverse", | ||
291 | 287 | "hoary-security main restricted universe multiverse", | ||
292 | 288 | "hoary-updates main restricted universe multiverse", | ||
293 | 289 | ]), | ||
294 | 290 | ], build) | ||
295 | 291 | |||
296 | 292 | def test_primary_archive_dependency_security(self): | ||
297 | 293 | # The primary archive dependency can be modified to behave as an | ||
298 | 294 | # embargoed archive that builds security updates. This is done by | ||
299 | 295 | # setting the SECURITY pocket dependencies (RELEASE and SECURITY) | ||
300 | 296 | # and following the component dependencies of the component where | ||
301 | 297 | # the source was last published in the primary archive. | ||
302 | 298 | ppa = self.makeArchive() | ||
303 | 299 | ppa.addArchiveDependency( | ||
304 | 300 | self.ubuntu.main_archive, PackagePublishingPocket.SECURITY) | ||
305 | 301 | build = self.makeBuild(archive=ppa) | ||
306 | 302 | self.assertPrimaryCurrentComponent("universe", build) | ||
307 | 303 | self.assertSourcesList( | ||
308 | 304 | [(self.ubuntu.main_archive, [ | ||
309 | 305 | "hoary main universe", | ||
310 | 306 | "hoary-security main universe", | ||
311 | 307 | ]), | ||
312 | 308 | ], build) | ||
313 | 309 | self.publisher.getPubSource( | ||
314 | 310 | sourcename="with-ancestry", version="1.0", | ||
315 | 311 | archive=self.ubuntu.main_archive) | ||
316 | 312 | [build_with_ancestry] = self.publisher.getPubSource( | ||
317 | 313 | sourcename="with-ancestry", version="1.1", | ||
318 | 314 | archive=ppa).createMissingBuilds() | ||
319 | 315 | self.assertPrimaryCurrentComponent("main", build_with_ancestry) | ||
320 | 316 | self.assertSourcesList( | ||
321 | 317 | [(self.ubuntu.main_archive, [ | ||
322 | 318 | "hoary main", | ||
323 | 319 | "hoary-security main", | ||
324 | 320 | ]), | ||
325 | 321 | ], build_with_ancestry) | ||
326 | 322 | |||
327 | 323 | def test_primary_archive_dependency_release(self): | ||
328 | 324 | # The primary archive dependency can be modified to behave as a | ||
329 | 325 | # pristine build environment based only on what was included in the | ||
330 | 326 | # original release of the corresponding series. | ||
331 | 327 | ppa = self.makeArchive() | ||
332 | 328 | ppa.addArchiveDependency( | ||
333 | 329 | self.ubuntu.main_archive, PackagePublishingPocket.RELEASE, | ||
334 | 330 | getUtility(IComponentSet)["restricted"]) | ||
335 | 331 | build = self.makeBuild(archive=ppa) | ||
336 | 332 | self.assertSourcesList( | ||
337 | 333 | [(self.ubuntu.main_archive, ["hoary main restricted"])], build) | ||
338 | 334 | |||
339 | 335 | def test_primary_archive_dependency_proposed(self): | ||
340 | 336 | # The primary archive dependency can be modified to extend the build | ||
341 | 337 | # environment for PROPOSED. | ||
342 | 338 | ppa = self.makeArchive() | ||
343 | 339 | ppa.addArchiveDependency( | ||
344 | 340 | self.ubuntu.main_archive, PackagePublishingPocket.PROPOSED, | ||
345 | 341 | getUtility(IComponentSet)["multiverse"]) | ||
346 | 342 | build = self.makeBuild(archive=ppa) | ||
347 | 343 | self.assertSourcesList( | ||
348 | 344 | [(self.ubuntu.main_archive, [ | ||
349 | 345 | "hoary main restricted universe multiverse", | ||
350 | 346 | "hoary-security main restricted universe multiverse", | ||
351 | 347 | "hoary-updates main restricted universe multiverse", | ||
352 | 348 | "hoary-proposed main restricted universe multiverse", | ||
353 | 349 | ]), | ||
354 | 350 | ], build) | ||
355 | 351 | |||
356 | 352 | def test_primary_archive_dependency_backports(self): | ||
357 | 353 | # The primary archive dependency can be modified to extend the build | ||
358 | 354 | # environment for PROPOSED. | ||
359 | 355 | ppa = self.makeArchive() | ||
360 | 356 | ppa.addArchiveDependency( | ||
361 | 357 | self.ubuntu.main_archive, PackagePublishingPocket.BACKPORTS, | ||
362 | 358 | getUtility(IComponentSet)["multiverse"]) | ||
363 | 359 | build = self.makeBuild(archive=ppa) | ||
364 | 360 | self.assertSourcesList( | ||
365 | 361 | [(self.ubuntu.main_archive, [ | ||
366 | 362 | "hoary main restricted universe multiverse", | ||
367 | 363 | "hoary-security main restricted universe multiverse", | ||
368 | 364 | "hoary-updates main restricted universe multiverse", | ||
369 | 365 | "hoary-backports main restricted universe multiverse", | ||
370 | 366 | ]), | ||
371 | 367 | ], build) | ||
372 | 368 | |||
373 | 369 | def test_partner(self): | ||
374 | 370 | # Similarly to what happens with PPA builds, partner builds may | ||
375 | 371 | # depend on any component in the primary archive. This behaviour | ||
376 | 372 | # allows scenarios where partner packages may use other | ||
377 | 373 | # restricted/non-free applications from multiverse, and also other | ||
378 | 374 | # partner applications. | ||
379 | 375 | primary, partner = self.ubuntu.all_distro_archives | ||
380 | 376 | self.publisher.getPubBinaries( | ||
381 | 377 | archive=partner, component="partner", | ||
382 | 378 | status=PackagePublishingStatus.PUBLISHED) | ||
383 | 379 | build = self.makeBuild(archive=partner, component="partner") | ||
384 | 380 | self.assertSourcesList( | ||
385 | 381 | [(partner, ["hoary partner"]), | ||
386 | 382 | (primary, [ | ||
387 | 383 | "hoary main restricted universe multiverse", | ||
388 | 384 | "hoary-security main restricted universe multiverse", | ||
389 | 385 | "hoary-updates main restricted universe multiverse", | ||
390 | 386 | ]), | ||
391 | 387 | ], build) | ||
392 | 388 | |||
393 | 389 | def test_partner_proposed(self): | ||
394 | 390 | # The partner archive's PROPOSED pocket builds against itself, but | ||
395 | 391 | # still uses the default UPDATES dependency for the primary archive | ||
396 | 392 | # unless overridden by ArchiveDependency. | ||
397 | 393 | primary, partner = self.ubuntu.all_distro_archives | ||
398 | 394 | self.publisher.getPubBinaries( | ||
399 | 395 | archive=partner, component="partner", | ||
400 | 396 | status=PackagePublishingStatus.PUBLISHED) | ||
401 | 397 | self.publisher.getPubBinaries( | ||
402 | 398 | archive=partner, component="partner", | ||
403 | 399 | status=PackagePublishingStatus.PUBLISHED, | ||
404 | 400 | pocket=PackagePublishingPocket.PROPOSED) | ||
405 | 401 | build = self.makeBuild( | ||
406 | 402 | archive=partner, component="partner", | ||
407 | 403 | pocket=PackagePublishingPocket.PROPOSED) | ||
408 | 404 | self.assertSourcesList( | ||
409 | 405 | [(partner, [ | ||
410 | 406 | "hoary partner", | ||
411 | 407 | "hoary-proposed partner", | ||
412 | 408 | ]), | ||
413 | 409 | (primary, [ | ||
414 | 410 | "hoary main restricted universe multiverse", | ||
415 | 411 | "hoary-security main restricted universe multiverse", | ||
416 | 412 | "hoary-updates main restricted universe multiverse", | ||
417 | 413 | ]), | ||
418 | 414 | ], build) | ||
419 | 415 | |||
420 | 416 | def test_archive_external_dependencies(self): | ||
421 | 417 | # An archive can be manually given additional external dependencies. | ||
422 | 418 | # If present, "%(series)s" is replaced with the series name for the | ||
423 | 419 | # build being dispatched. | ||
424 | 420 | ppa = self.makeArchive(publish_binary=True) | ||
425 | 421 | ppa.external_dependencies = ( | ||
426 | 422 | "deb http://user:pass@repository zoing everything\n" | ||
427 | 423 | "deb http://user:pass@repository %(series)s public private\n" | ||
428 | 424 | "deb http://user:pass@repository %(series)s-extra public") | ||
429 | 425 | build = self.makeBuild(archive=ppa) | ||
430 | 426 | self.assertSourcesList( | ||
431 | 427 | [(ppa, ["hoary main"]), | ||
432 | 428 | ("deb http://user:pass@repository", [ | ||
433 | 429 | "zoing everything", | ||
434 | 430 | "hoary public private", | ||
435 | 431 | "hoary-extra public", | ||
436 | 432 | ]), | ||
437 | 433 | (self.ubuntu.main_archive, [ | ||
438 | 434 | "hoary main restricted universe multiverse", | ||
439 | 435 | "hoary-security main restricted universe multiverse", | ||
440 | 436 | "hoary-updates main restricted universe multiverse", | ||
441 | 437 | ]), | ||
442 | 438 | ], build) | ||
443 | 439 | |||
444 | 440 | def test_build_external_dependencies(self): | ||
445 | 441 | # A single build can be manually given additional external | ||
446 | 442 | # dependencies. | ||
447 | 443 | ppa = self.makeArchive(publish_binary=True) | ||
448 | 444 | build = self.makeBuild(archive=ppa) | ||
449 | 445 | build.api_external_dependencies = ( | ||
450 | 446 | "deb http://user:pass@repository foo bar") | ||
451 | 447 | self.assertSourcesList( | ||
452 | 448 | [(ppa, ["hoary main"]), | ||
453 | 449 | ("deb http://user:pass@repository", ["foo bar"]), | ||
454 | 450 | (self.ubuntu.main_archive, [ | ||
455 | 451 | "hoary main restricted universe multiverse", | ||
456 | 452 | "hoary-security main restricted universe multiverse", | ||
457 | 453 | "hoary-updates main restricted universe multiverse", | ||
458 | 454 | ]), | ||
459 | 455 | ], build) | ||
460 | 456 | |||
461 | 457 | def test_build_tools(self): | ||
462 | 458 | # We can force an extra build tools line to be added to | ||
463 | 459 | # sources.list, which is useful for specialised build types. | ||
464 | 460 | ppa = self.makeArchive(publish_binary=True) | ||
465 | 461 | build = self.makeBuild(archive=ppa) | ||
466 | 462 | self.assertSourcesList( | ||
467 | 463 | [(ppa, ["hoary main"]), | ||
468 | 464 | ("deb http://example.org", ["hoary main"]), | ||
469 | 465 | (self.ubuntu.main_archive, [ | ||
470 | 466 | "hoary main restricted universe multiverse", | ||
471 | 467 | "hoary-security main restricted universe multiverse", | ||
472 | 468 | "hoary-updates main restricted universe multiverse", | ||
473 | 469 | ]), | ||
474 | 470 | ], build, tools_source="deb http://example.org %(series)s main") | ||
475 | 471 | |||
476 | 472 | def test_build_tools_bad_formatting(self): | ||
477 | 473 | # If tools_source is badly formatted, we log the error but don't | ||
478 | 474 | # blow up. (Note the missing "s" at the end of "%(series)".) | ||
479 | 475 | ppa = self.makeArchive(publish_binary=True) | ||
480 | 476 | build = self.makeBuild(archive=ppa) | ||
481 | 477 | logger = BufferLogger() | ||
482 | 478 | self.assertSourcesList( | ||
483 | 479 | [(ppa, ["hoary main"]), | ||
484 | 480 | (self.ubuntu.main_archive, [ | ||
485 | 481 | "hoary main restricted universe multiverse", | ||
486 | 482 | "hoary-security main restricted universe multiverse", | ||
487 | 483 | "hoary-updates main restricted universe multiverse", | ||
488 | 484 | ]), | ||
489 | 485 | ], | ||
490 | 486 | build, tools_source="deb http://example.org %(series) main", | ||
491 | 487 | logger=logger) | ||
492 | 488 | self.assertThat(logger.getLogBuffer(), StartsWith( | ||
493 | 489 | "ERROR Exception processing build tools sources.list entry:\n")) | ||
494 | 490 | |||
495 | 491 | def test_overlay(self): | ||
496 | 492 | # An overlay distroseries is a derived distribution which works like | ||
497 | 493 | # a PPA. This means that the parent's details gets added to the | ||
498 | 494 | # sources.list passed to the builders. | ||
499 | 495 | depdistro = self.factory.makeDistribution( | ||
500 | 496 | "depdistro", publish_base_url="http://archive.launchpad.dev/") | ||
501 | 497 | depseries = self.factory.makeDistroSeries( | ||
502 | 498 | distribution=depdistro, name="depseries") | ||
503 | 499 | self.factory.makeDistroArchSeries( | ||
504 | 500 | distroseries=depseries, architecturetag="i386") | ||
505 | 501 | self.publisher.addFakeChroots(depseries) | ||
506 | 502 | for component_name in self.ubuntu_components: | ||
507 | 503 | component = getUtility(IComponentSet)[component_name] | ||
508 | 504 | self.factory.makeComponentSelection(depseries, component) | ||
509 | 505 | self.factory.makeDistroSeriesParent( | ||
510 | 506 | derived_series=self.hoary, parent_series=depseries, | ||
511 | 507 | initialized=True, is_overlay=True, | ||
512 | 508 | pocket=PackagePublishingPocket.SECURITY, | ||
513 | 509 | component=getUtility(IComponentSet)["universe"]) | ||
514 | 510 | build = self.makeBuild() | ||
515 | 511 | self.assertSourcesList( | ||
516 | 512 | [(self.ubuntu.main_archive, ["hoary main"]), | ||
517 | 513 | (depdistro.main_archive, [ | ||
518 | 514 | "depseries main universe", | ||
519 | 515 | "depseries-security main universe", | ||
520 | 516 | ]), | ||
521 | 517 | ], build) | ||
522 | 0 | 518 | ||
523 | === removed file 'lib/lp/soyuz/doc/archive-dependencies.txt' | |||
524 | --- lib/lp/soyuz/doc/archive-dependencies.txt 2016-04-07 00:04:42 +0000 | |||
525 | +++ lib/lp/soyuz/doc/archive-dependencies.txt 1970-01-01 00:00:00 +0000 | |||
526 | @@ -1,637 +0,0 @@ | |||
527 | 1 | = Archive dependencies = | ||
528 | 2 | |||
529 | 3 | `ArchiveDependencies` class models archive dependencies mechanics and | ||
530 | 4 | is used to provided the contents of 'sources_list' file used to build | ||
531 | 5 | sources in the given IBuildQueue context. | ||
532 | 6 | |||
533 | 7 | |||
534 | 8 | == Testing scenario setup == | ||
535 | 9 | |||
536 | 10 | We use `SoyuzTestPublisher` to generate a source publications and | ||
537 | 11 | build candidates for ubuntu/hoary. | ||
538 | 12 | |||
539 | 13 | >>> from lp.registry.interfaces.distribution import IDistributionSet | ||
540 | 14 | >>> from lp.soyuz.interfaces.component import IComponentSet | ||
541 | 15 | >>> from lp.soyuz.tests.test_publishing import SoyuzTestPublisher | ||
542 | 16 | >>> from lp.testing import login | ||
543 | 17 | |||
544 | 18 | >>> login('foo.bar@canonical.com') | ||
545 | 19 | |||
546 | 20 | >>> test_publisher = SoyuzTestPublisher() | ||
547 | 21 | |||
548 | 22 | >>> ubuntu = getUtility(IDistributionSet).getByName('ubuntu') | ||
549 | 23 | >>> hoary = ubuntu.getSeries('hoary') | ||
550 | 24 | |||
551 | 25 | >>> test_publisher.addFakeChroots(hoary) | ||
552 | 26 | >>> _ = test_publisher.setUpDefaultDistroSeries(hoary) | ||
553 | 27 | |||
554 | 28 | >>> ubuntu_components = [ | ||
555 | 29 | ... 'main', 'restricted', 'universe', 'multiverse', 'partner'] | ||
556 | 30 | >>> for component_name in ubuntu_components: | ||
557 | 31 | ... component = getUtility(IComponentSet)[component_name] | ||
558 | 32 | ... if component not in hoary.components: | ||
559 | 33 | ... _ = factory.makeComponentSelection(hoary, component) | ||
560 | 34 | |||
561 | 35 | |||
562 | 36 | == Static dependency maps == | ||
563 | 37 | |||
564 | 38 | `pocket_dependencies` contains a static map of the default ubuntu | ||
565 | 39 | pocket dependencies. | ||
566 | 40 | |||
567 | 41 | >>> from lp.soyuz.adapters.archivedependencies import pocket_dependencies | ||
568 | 42 | |||
569 | 43 | >>> def show_pocket_deps(): | ||
570 | 44 | ... print "Pocket | Dependencies" | ||
571 | 45 | ... print "----------+---------------" | ||
572 | 46 | ... for (key, value) in sorted(pocket_dependencies.items()): | ||
573 | 47 | ... print "%7s |" % (key.name,), | ||
574 | 48 | ... for pocket in value: | ||
575 | 49 | ... print pocket.name, | ||
576 | 50 | |||
577 | 51 | |||
578 | 52 | >>> show_pocket_deps() | ||
579 | 53 | Pocket | Dependencies | ||
580 | 54 | ----------+--------------- | ||
581 | 55 | RELEASE | RELEASE | ||
582 | 56 | SECURITY | RELEASE SECURITY | ||
583 | 57 | UPDATES | RELEASE SECURITY UPDATES | ||
584 | 58 | PROPOSED | RELEASE SECURITY UPDATES PROPOSED | ||
585 | 59 | BACKPORTS | RELEASE SECURITY UPDATES BACKPORTS | ||
586 | 60 | |||
587 | 61 | |||
588 | 62 | == 'Ogre' components == | ||
589 | 63 | |||
590 | 64 | The ubuntu 'ogre-model' ensures that build dependencies are | ||
591 | 65 | consistently spread according to the source target component, i.e. a | ||
592 | 66 | source published in 'main' component is only allowed to depend on | ||
593 | 67 | binaries also published in 'main', on the other hand a source | ||
594 | 68 | published in 'universe' is allowed to depend on binaries published in | ||
595 | 69 | 'main' and 'universe' components. | ||
596 | 70 | |||
597 | 71 | A proper name for this "model" would be 'cross-component-dependency'. | ||
598 | 72 | |||
599 | 73 | >>> from lp.services.database.sqlbase import flush_database_caches | ||
600 | 74 | |||
601 | 75 | >>> from zope.security.proxy import removeSecurityProxy | ||
602 | 76 | >>> from lp.registry.interfaces.pocket import ( | ||
603 | 77 | ... PackagePublishingPocket) | ||
604 | 78 | >>> from lp.soyuz.adapters.archivedependencies import ( | ||
605 | 79 | ... get_components_for_context) | ||
606 | 80 | >>> from lp.soyuz.enums import ArchivePurpose | ||
607 | 81 | |||
608 | 82 | >>> def testOgreComponents(build): | ||
609 | 83 | ... print " Component | Ogre-Model" | ||
610 | 84 | ... print "-----------+---------------" | ||
611 | 85 | ... for component in ubuntu_components: | ||
612 | 86 | ... component = getUtility(IComponentSet)[component] | ||
613 | 87 | ... npub = removeSecurityProxy(build.current_source_publication) | ||
614 | 88 | ... npub.component = component | ||
615 | 89 | ... flush_database_caches() | ||
616 | 90 | ... components_term = " ".join(get_components_for_context( | ||
617 | 91 | ... build.current_component, build.distro_series, | ||
618 | 92 | ... build.pocket)) | ||
619 | 93 | ... print '%10s | %s' % (build.current_component.name, | ||
620 | 94 | ... components_term) | ||
621 | 95 | |||
622 | 96 | >>> archive = factory.makeArchive( | ||
623 | 97 | ... distribution=ubuntu, purpose=ArchivePurpose.PRIMARY) | ||
624 | 98 | >>> ogre_build = factory.makeBinaryPackageBuild( | ||
625 | 99 | ... distroarchseries=hoary.architectures[0], archive=archive, | ||
626 | 100 | ... pocket=PackagePublishingPocket.RELEASE) | ||
627 | 101 | >>> testOgreComponents(ogre_build) | ||
628 | 102 | Component | Ogre-Model | ||
629 | 103 | -----------+--------------- | ||
630 | 104 | main | main | ||
631 | 105 | restricted | main restricted | ||
632 | 106 | universe | main universe | ||
633 | 107 | multiverse | main restricted universe multiverse | ||
634 | 108 | partner | partner | ||
635 | 109 | |||
636 | 110 | Series with strict_supported_component_dependencies=False additionally allow | ||
637 | 111 | source packages in 'supported' components (main and restricted) to | ||
638 | 112 | build-depend on binary packages in 'unsupported' components (universe and | ||
639 | 113 | multiverse). | ||
640 | 114 | |||
641 | 115 | >>> from lp.buildmaster.interfaces.processor import IProcessorSet | ||
642 | 116 | |||
643 | 117 | >>> lax_distroseries = factory.makeDistroSeries( | ||
644 | 118 | ... distribution=archive.distribution, name='lax') | ||
645 | 119 | >>> lax_distroseries.strict_supported_component_dependencies = False | ||
646 | 120 | >>> lax_distroarchseries = factory.makeDistroArchSeries( | ||
647 | 121 | ... distroseries=lax_distroseries, architecturetag='i386', | ||
648 | 122 | ... processor=getUtility(IProcessorSet).getByName('386')) | ||
649 | 123 | >>> test_publisher.addFakeChroots(lax_distroseries) | ||
650 | 124 | >>> for component_name in ubuntu_components: | ||
651 | 125 | ... component = getUtility(IComponentSet)[component_name] | ||
652 | 126 | ... _ = factory.makeComponentSelection(lax_distroseries, component) | ||
653 | 127 | >>> lax_ogre_build = factory.makeBinaryPackageBuild( | ||
654 | 128 | ... distroarchseries=lax_distroarchseries, archive=archive, | ||
655 | 129 | ... pocket=PackagePublishingPocket.RELEASE) | ||
656 | 130 | >>> testOgreComponents(lax_ogre_build) | ||
657 | 131 | Component | Ogre-Model | ||
658 | 132 | -----------+--------------- | ||
659 | 133 | main | main universe | ||
660 | 134 | restricted | main restricted universe multiverse | ||
661 | 135 | universe | main universe | ||
662 | 136 | multiverse | main restricted universe multiverse | ||
663 | 137 | partner | partner | ||
664 | 138 | |||
665 | 139 | As fixed for bug #198936, builds for the BACKPORTS pocket are allowed | ||
666 | 140 | to use any component available, independently of the component they | ||
667 | 141 | are currently published. This special-case is important because it | ||
668 | 142 | avoids changes to accommodate the backported source in the already | ||
669 | 143 | released series. | ||
670 | 144 | |||
671 | 145 | Ultimately, it means that a build targeted to the BACKPORTS pocket | ||
672 | 146 | will behave as if it were published in the multiverse component, | ||
673 | 147 | despite the component it is actually published in. | ||
674 | 148 | |||
675 | 149 | >>> back_build = factory.makeBinaryPackageBuild( | ||
676 | 150 | ... distroarchseries=hoary.architectures[0], | ||
677 | 151 | ... archive=archive, pocket=PackagePublishingPocket.BACKPORTS) | ||
678 | 152 | >>> testOgreComponents(back_build) | ||
679 | 153 | Component | Ogre-Model | ||
680 | 154 | -----------+--------------- | ||
681 | 155 | main | main restricted universe multiverse | ||
682 | 156 | restricted | main restricted universe multiverse | ||
683 | 157 | universe | main restricted universe multiverse | ||
684 | 158 | multiverse | main restricted universe multiverse | ||
685 | 159 | partner | main restricted universe multiverse | ||
686 | 160 | |||
687 | 161 | |||
688 | 162 | == Sources.list contents for building == | ||
689 | 163 | |||
690 | 164 | We will use Celso's PPA for testing these mechanisms. | ||
691 | 165 | |||
692 | 166 | >>> from lp.registry.interfaces.person import IPersonSet | ||
693 | 167 | >>> cprov = getUtility(IPersonSet).getByName('cprov') | ||
694 | 168 | >>> print cprov.archive.displayname | ||
695 | 169 | PPA for Celso Providelo | ||
696 | 170 | |||
697 | 171 | Non-primary archives by default use primary Release, Security and Updates | ||
698 | 172 | pockets and all its available components. | ||
699 | 173 | |||
700 | 174 | >>> from lp.soyuz.adapters.archivedependencies import ( | ||
701 | 175 | ... default_component_dependency_name, default_pocket_dependency) | ||
702 | 176 | |||
703 | 177 | >>> print default_pocket_dependency | ||
704 | 178 | Updates | ||
705 | 179 | |||
706 | 180 | >>> print default_component_dependency_name | ||
707 | 181 | multiverse | ||
708 | 182 | |||
709 | 183 | The default values get applied to their corresponding dependency maps | ||
710 | 184 | and then will expand to distinct values that will be used to produce | ||
711 | 185 | the building 'sources_list' contents. | ||
712 | 186 | |||
713 | 187 | >>> for pocket in pocket_dependencies[default_pocket_dependency]: | ||
714 | 188 | ... print pocket | ||
715 | 189 | Release | ||
716 | 190 | Security | ||
717 | 191 | Updates | ||
718 | 192 | |||
719 | 193 | >>> for component_name in get_components_for_context( | ||
720 | 194 | ... getUtility(IComponentSet)[default_component_dependency_name], | ||
721 | 195 | ... hoary, pocket): | ||
722 | 196 | ... print component_name | ||
723 | 197 | main | ||
724 | 198 | restricted | ||
725 | 199 | universe | ||
726 | 200 | multiverse | ||
727 | 201 | |||
728 | 202 | We will create a testing source publication and probe its build | ||
729 | 203 | environment. | ||
730 | 204 | |||
731 | 205 | >>> pub_source = test_publisher.getPubSource( | ||
732 | 206 | ... version='1.1', archive=cprov.archive) | ||
733 | 207 | >>> [a_build] = pub_source.createMissingBuilds() | ||
734 | 208 | |||
735 | 209 | Now we can verify if get_sources_list_for_building() method returns the | ||
736 | 210 | expected content for building the just-created source. | ||
737 | 211 | |||
738 | 212 | >>> from lp.soyuz.adapters.archivedependencies import ( | ||
739 | 213 | ... get_sources_list_for_building) | ||
740 | 214 | |||
741 | 215 | >>> def print_building_sources_list(candidate): | ||
742 | 216 | ... sources_list = get_sources_list_for_building( | ||
743 | 217 | ... candidate, candidate.distro_arch_series, | ||
744 | 218 | ... candidate.source_package_release.name) | ||
745 | 219 | ... for line in sources_list: | ||
746 | 220 | ... print line | ||
747 | 221 | |||
748 | 222 | Note that only the default ubuntu dependencies for a public PPA will be | ||
749 | 223 | considered when building the source candidate. That's because there is | ||
750 | 224 | no binary published in Celso's PPA hoary/i386, so there is | ||
751 | 225 | no need to request the builder to load its archive indexes. | ||
752 | 226 | |||
753 | 227 | >>> from lp.soyuz.enums import PackagePublishingStatus | ||
754 | 228 | |||
755 | 229 | >>> cprov.archive.getAllPublishedBinaries( | ||
756 | 230 | ... distroarchseries=a_build.distro_arch_series, | ||
757 | 231 | ... status=PackagePublishingStatus.PUBLISHED).count() | ||
758 | 232 | 0 | ||
759 | 233 | |||
760 | 234 | >>> print_building_sources_list(a_build) | ||
761 | 235 | deb http://archive.launchpad.dev/ubuntu hoary | ||
762 | 236 | main restricted universe multiverse | ||
763 | 237 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
764 | 238 | main restricted universe multiverse | ||
765 | 239 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
766 | 240 | main restricted universe multiverse | ||
767 | 241 | |||
768 | 242 | Once we publish a test binary in Celso's PPA hoary/i386, | ||
769 | 243 | this archive becomes relevant for building, and thus listed in the | ||
770 | 244 | returned 'sources_list' content. | ||
771 | 245 | |||
772 | 246 | >>> pub_binaries = test_publisher.getPubBinaries( | ||
773 | 247 | ... binaryname='dep-bin', archive=cprov.archive, | ||
774 | 248 | ... status=PackagePublishingStatus.PUBLISHED) | ||
775 | 249 | |||
776 | 250 | >>> print_building_sources_list(a_build) | ||
777 | 251 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
778 | 252 | deb http://archive.launchpad.dev/ubuntu hoary | ||
779 | 253 | main restricted universe multiverse | ||
780 | 254 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
781 | 255 | main restricted universe multiverse | ||
782 | 256 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
783 | 257 | main restricted universe multiverse | ||
784 | 258 | |||
785 | 259 | Similarly, unpopulated PPA dependencies are *not* listed in the building | ||
786 | 260 | 'sources_list'. | ||
787 | 261 | |||
788 | 262 | >>> mark = getUtility(IPersonSet).getByName('mark') | ||
789 | 263 | >>> archive_dependency = cprov.archive.addArchiveDependency( | ||
790 | 264 | ... mark.archive, PackagePublishingPocket.RELEASE, | ||
791 | 265 | ... getUtility(IComponentSet)['main']) | ||
792 | 266 | >>> print_building_sources_list(a_build) | ||
793 | 267 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
794 | 268 | deb http://archive.launchpad.dev/ubuntu hoary | ||
795 | 269 | main restricted universe multiverse | ||
796 | 270 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
797 | 271 | main restricted universe multiverse | ||
798 | 272 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
799 | 273 | main restricted universe multiverse | ||
800 | 274 | |||
801 | 275 | But *populated* PPA dependencies *are* listed in the building 'sources_list'. | ||
802 | 276 | |||
803 | 277 | >>> pub_binaries = test_publisher.getPubBinaries( | ||
804 | 278 | ... binaryname='dep-bin', archive=mark.archive, | ||
805 | 279 | ... status=PackagePublishingStatus.PUBLISHED) | ||
806 | 280 | >>> print_building_sources_list(a_build) | ||
807 | 281 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
808 | 282 | deb http://ppa.launchpad.dev/mark/ppa/ubuntu hoary main | ||
809 | 283 | deb http://archive.launchpad.dev/ubuntu hoary | ||
810 | 284 | main restricted universe multiverse | ||
811 | 285 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
812 | 286 | main restricted universe multiverse | ||
813 | 287 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
814 | 288 | main restricted universe multiverse | ||
815 | 289 | |||
816 | 290 | Dependencies for series with strict_supported_component_dependencies=False | ||
817 | 291 | are reasonable too. PPAs only have the 'main' component. | ||
818 | 292 | |||
819 | 293 | >>> lax_pub_source = test_publisher.getPubSource( | ||
820 | 294 | ... version='1.2', distroseries=lax_distroseries, | ||
821 | 295 | ... archive=cprov.archive) | ||
822 | 296 | >>> [lax_build] = lax_pub_source.createMissingBuilds() | ||
823 | 297 | >>> _ = test_publisher.getPubBinaries( | ||
824 | 298 | ... binaryname='dep-bin', distroseries=lax_distroseries, | ||
825 | 299 | ... archive=cprov.archive, status=PackagePublishingStatus.PUBLISHED) | ||
826 | 300 | >>> _ = test_publisher.getPubBinaries( | ||
827 | 301 | ... binaryname='dep-bin', distroseries=lax_distroseries, | ||
828 | 302 | ... archive=mark.archive, status=PackagePublishingStatus.PUBLISHED) | ||
829 | 303 | >>> print_building_sources_list(lax_build) | ||
830 | 304 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu lax main | ||
831 | 305 | deb http://ppa.launchpad.dev/mark/ppa/ubuntu lax main | ||
832 | 306 | deb http://archive.launchpad.dev/ubuntu lax | ||
833 | 307 | main restricted universe multiverse | ||
834 | 308 | deb http://archive.launchpad.dev/ubuntu lax-security | ||
835 | 309 | main restricted universe multiverse | ||
836 | 310 | deb http://archive.launchpad.dev/ubuntu lax-updates | ||
837 | 311 | main restricted universe multiverse | ||
838 | 312 | |||
839 | 313 | >>> cprov.archive.removeArchiveDependency(mark.archive) | ||
840 | 314 | |||
841 | 315 | What when we supply invalid dependencies, an exception is raised. | ||
842 | 316 | |||
843 | 317 | >>> cprov.archive.external_dependencies = ( | ||
844 | 318 | ... "Malformed format string here --> %(series)") | ||
845 | 319 | Traceback (most recent call last): | ||
846 | 320 | InvalidExternalDependencies: (InvalidExternalDependencies(...), | ||
847 | 321 | "Invalid external dependencies:\nMalformed format string here | ||
848 | 322 | --> %(series): Must start with 'deb'\nMalformed format string here | ||
849 | 323 | --> %(series): Invalid URL\n") | ||
850 | 324 | |||
851 | 325 | |||
852 | 326 | == Overriding default primary archive dependencies == | ||
853 | 327 | |||
854 | 328 | Despite being private or public, default primary archive dependencies | ||
855 | 329 | can be overridden by simply creating a `ArchiveDependency`record | ||
856 | 330 | targeted to the primary archive. | ||
857 | 331 | |||
858 | 332 | The 'pocket' and 'component' dependency attributes can be adjusted to | ||
859 | 333 | produce the desired build behaviour. | ||
860 | 334 | |||
861 | 335 | By default, public PPAs depend on all of the pocket dependencies of | ||
862 | 336 | UPDATES, and all of the primary archive's 'multiverse' component | ||
863 | 337 | dependencies. | ||
864 | 338 | |||
865 | 339 | >>> print_building_sources_list(a_build) | ||
866 | 340 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
867 | 341 | deb http://archive.launchpad.dev/ubuntu hoary | ||
868 | 342 | main restricted universe multiverse | ||
869 | 343 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
870 | 344 | main restricted universe multiverse | ||
871 | 345 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
872 | 346 | main restricted universe multiverse | ||
873 | 347 | |||
874 | 348 | The default build behaviour will remain unchanged when we override the | ||
875 | 349 | default primary archive dependencies with exactly the same values. | ||
876 | 350 | |||
877 | 351 | >>> default_dependency = cprov.archive.addArchiveDependency( | ||
878 | 352 | ... ubuntu.main_archive, PackagePublishingPocket.UPDATES, | ||
879 | 353 | ... getUtility(IComponentSet)['multiverse']) | ||
880 | 354 | |||
881 | 355 | >>> print_building_sources_list(a_build) | ||
882 | 356 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
883 | 357 | deb http://archive.launchpad.dev/ubuntu hoary | ||
884 | 358 | main restricted universe multiverse | ||
885 | 359 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
886 | 360 | main restricted universe multiverse | ||
887 | 361 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
888 | 362 | main restricted universe multiverse | ||
889 | 363 | |||
890 | 364 | >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive) | ||
891 | 365 | |||
892 | 366 | The dependency can be modified to behave as an embargoed archive that | ||
893 | 367 | builds security updates. This is done by setting the SECURITY pocket | ||
894 | 368 | dependencies (RELEASE and SECURITY) and following the component | ||
895 | 369 | dependencies of the component where the source was last published in | ||
896 | 370 | the primary archive. | ||
897 | 371 | |||
898 | 372 | >>> security_dependency = cprov.archive.addArchiveDependency( | ||
899 | 373 | ... ubuntu.main_archive, PackagePublishingPocket.SECURITY) | ||
900 | 374 | |||
901 | 375 | >>> from lp.soyuz.adapters.archivedependencies import ( | ||
902 | 376 | ... get_primary_current_component) | ||
903 | 377 | |||
904 | 378 | >>> print get_primary_current_component(a_build.archive, | ||
905 | 379 | ... a_build.distro_series, a_build.source_package_release.name).name | ||
906 | 380 | universe | ||
907 | 381 | |||
908 | 382 | >>> print_building_sources_list(a_build) | ||
909 | 383 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
910 | 384 | deb http://archive.launchpad.dev/ubuntu hoary | ||
911 | 385 | main universe | ||
912 | 386 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
913 | 387 | main universe | ||
914 | 388 | |||
915 | 389 | >>> _ = test_publisher.getPubSource( | ||
916 | 390 | ... sourcename='with-ancestry', version='1.0', | ||
917 | 391 | ... archive=ubuntu.main_archive) | ||
918 | 392 | >>> [build_with_ancestry] = test_publisher.getPubSource( | ||
919 | 393 | ... sourcename='with-ancestry', version='1.1', | ||
920 | 394 | ... archive=cprov.archive).createMissingBuilds() | ||
921 | 395 | >>> print get_primary_current_component( | ||
922 | 396 | ... build_with_ancestry.archive, build_with_ancestry.distro_series, | ||
923 | 397 | ... build_with_ancestry.source_package_release.name).name | ||
924 | 398 | main | ||
925 | 399 | >>> print_building_sources_list(build_with_ancestry) | ||
926 | 400 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
927 | 401 | deb http://archive.launchpad.dev/ubuntu hoary main | ||
928 | 402 | deb http://archive.launchpad.dev/ubuntu hoary-security main | ||
929 | 403 | |||
930 | 404 | >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive) | ||
931 | 405 | |||
932 | 406 | It's also possible to modify the PPA to act as a super-free and | ||
933 | 407 | pristine build environment based only on what was included in the | ||
934 | 408 | original ubuntu release. | ||
935 | 409 | |||
936 | 410 | >>> release_dependency = cprov.archive.addArchiveDependency( | ||
937 | 411 | ... ubuntu.main_archive, PackagePublishingPocket.RELEASE, | ||
938 | 412 | ... getUtility(IComponentSet)['restricted']) | ||
939 | 413 | |||
940 | 414 | >>> print_building_sources_list(a_build) | ||
941 | 415 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
942 | 416 | deb http://archive.launchpad.dev/ubuntu hoary main restricted | ||
943 | 417 | |||
944 | 418 | >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive) | ||
945 | 419 | |||
946 | 420 | The PPA can also be configured to extend the ubuntu PROPOSED build | ||
947 | 421 | environment. | ||
948 | 422 | |||
949 | 423 | >>> proposed_dependency = cprov.archive.addArchiveDependency( | ||
950 | 424 | ... ubuntu.main_archive, PackagePublishingPocket.PROPOSED, | ||
951 | 425 | ... getUtility(IComponentSet)['multiverse']) | ||
952 | 426 | |||
953 | 427 | >>> print_building_sources_list(a_build) | ||
954 | 428 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
955 | 429 | deb http://archive.launchpad.dev/ubuntu hoary | ||
956 | 430 | main restricted universe multiverse | ||
957 | 431 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
958 | 432 | main restricted universe multiverse | ||
959 | 433 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
960 | 434 | main restricted universe multiverse | ||
961 | 435 | deb http://archive.launchpad.dev/ubuntu hoary-proposed | ||
962 | 436 | main restricted universe multiverse | ||
963 | 437 | |||
964 | 438 | >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive) | ||
965 | 439 | |||
966 | 440 | Similarly an extension of the BACKPORTS environment can be set. | ||
967 | 441 | |||
968 | 442 | >>> backports_dependency = cprov.archive.addArchiveDependency( | ||
969 | 443 | ... ubuntu.main_archive, PackagePublishingPocket.BACKPORTS, | ||
970 | 444 | ... getUtility(IComponentSet)['multiverse']) | ||
971 | 445 | |||
972 | 446 | >>> print_building_sources_list(a_build) | ||
973 | 447 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
974 | 448 | deb http://archive.launchpad.dev/ubuntu hoary | ||
975 | 449 | main restricted universe multiverse | ||
976 | 450 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
977 | 451 | main restricted universe multiverse | ||
978 | 452 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
979 | 453 | main restricted universe multiverse | ||
980 | 454 | deb http://archive.launchpad.dev/ubuntu hoary-backports | ||
981 | 455 | main restricted universe multiverse | ||
982 | 456 | |||
983 | 457 | >>> cprov.archive.removeArchiveDependency(ubuntu.main_archive) | ||
984 | 458 | |||
985 | 459 | |||
986 | 460 | == Partner archive builds == | ||
987 | 461 | |||
988 | 462 | Similarly to what happens with PPA builds, PARTNER builds may depend | ||
989 | 463 | on any Ubuntu component in the PRIMARY archive. This behaviour allows | ||
990 | 464 | scenarios where partner packages may use other restricted/non-free | ||
991 | 465 | applications from 'multiverse', for instance 'sun-java', and also | ||
992 | 466 | other partner applications by default. | ||
993 | 467 | |||
994 | 468 | # Populate the ubuntutest PARTNER archive with one built and one | ||
995 | 469 | # pending build source. | ||
996 | 470 | >>> primary, partner = ubuntu.all_distro_archives | ||
997 | 471 | >>> unused_source = test_publisher.getPubSource( | ||
998 | 472 | ... archive=partner, component='partner') | ||
999 | 473 | >>> unused = test_publisher.getPubBinaries( | ||
1000 | 474 | ... pub_source=unused_source, | ||
1001 | 475 | ... status=PackagePublishingStatus.PUBLISHED) | ||
1002 | 476 | >>> pub_source = test_publisher.getPubSource( | ||
1003 | 477 | ... version='1.2', archive=partner, component='partner') | ||
1004 | 478 | >>> [partner_build] = pub_source.createMissingBuilds() | ||
1005 | 479 | |||
1006 | 480 | >>> print_building_sources_list(partner_build) | ||
1007 | 481 | deb http://archive.launchpad.dev/ubuntu-partner hoary partner | ||
1008 | 482 | deb http://archive.launchpad.dev/ubuntu hoary | ||
1009 | 483 | main restricted universe multiverse | ||
1010 | 484 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
1011 | 485 | main restricted universe multiverse | ||
1012 | 486 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
1013 | 487 | main restricted universe multiverse | ||
1014 | 488 | |||
1015 | 489 | PARTNER's PROPOSED pocket builds against itself, but still uses the | ||
1016 | 490 | default UPDATES dependency for PRIMARY unless overridden by | ||
1017 | 491 | ArchiveDependency. | ||
1018 | 492 | |||
1019 | 493 | >>> proposed_source = test_publisher.getPubSource( | ||
1020 | 494 | ... version='1.2', archive=partner, component='partner', | ||
1021 | 495 | ... pocket=PackagePublishingPocket.PROPOSED) | ||
1022 | 496 | >>> unused = test_publisher.getPubBinaries( | ||
1023 | 497 | ... archive=partner, distroseries=proposed_source.distroseries, | ||
1024 | 498 | ... pocket=PackagePublishingPocket.PROPOSED, | ||
1025 | 499 | ... status=PackagePublishingStatus.PUBLISHED) | ||
1026 | 500 | >>> [partner_proposed_build] = proposed_source.createMissingBuilds() | ||
1027 | 501 | |||
1028 | 502 | >>> print_building_sources_list(partner_proposed_build) | ||
1029 | 503 | deb http://archive.launchpad.dev/ubuntu-partner hoary partner | ||
1030 | 504 | deb http://archive.launchpad.dev/ubuntu-partner hoary-proposed partner | ||
1031 | 505 | deb http://archive.launchpad.dev/ubuntu hoary | ||
1032 | 506 | main restricted universe multiverse | ||
1033 | 507 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
1034 | 508 | main restricted universe multiverse | ||
1035 | 509 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
1036 | 510 | main restricted universe multiverse | ||
1037 | 511 | |||
1038 | 512 | == External build dependencies == | ||
1039 | 513 | |||
1040 | 514 | Via an administrator change, any PPA hosted in launchpad can be | ||
1041 | 515 | assigned to one or more 'external' build dependencies additionally to | ||
1042 | 516 | the internal ones. | ||
1043 | 517 | |||
1044 | 518 | There is a column on IArchive called 'external_dependencies' which can be set | ||
1045 | 519 | for any hosted PPA. It is a string listing the comma-separated external | ||
1046 | 520 | dependencies in the debian sources_list format. | ||
1047 | 521 | |||
1048 | 522 | deb http[s]://[user:pass@]<host>[/path] %(series)s[-pocket] [components] | ||
1049 | 523 | |||
1050 | 524 | The '%(series)s' part is optional and will be replaced on-the-fly with | ||
1051 | 525 | the series name for the build record being dispatched. | ||
1052 | 526 | |||
1053 | 527 | We will create some dependencies for Celso's PPA. | ||
1054 | 528 | |||
1055 | 529 | >>> cprov.archive.external_dependencies = ( | ||
1056 | 530 | ... "deb http://user:pass@repository zoing everything\n" | ||
1057 | 531 | ... "deb http://user:pass@repository %(series)s public private\n" | ||
1058 | 532 | ... "deb http://user:pass@repository %(series)s-extra public") | ||
1059 | 533 | |||
1060 | 534 | Now builds in Celso's PPA will use the external dependencies. | ||
1061 | 535 | |||
1062 | 536 | >>> print_building_sources_list(a_build) | ||
1063 | 537 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
1064 | 538 | deb http://user:pass@repository zoing everything | ||
1065 | 539 | deb http://user:pass@repository hoary public private | ||
1066 | 540 | deb http://user:pass@repository hoary-extra public | ||
1067 | 541 | deb http://archive.launchpad.dev/ubuntu hoary | ||
1068 | 542 | main restricted universe multiverse | ||
1069 | 543 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
1070 | 544 | main restricted universe multiverse | ||
1071 | 545 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
1072 | 546 | main restricted universe multiverse | ||
1073 | 547 | |||
1074 | 548 | >>> cprov.archive.external_dependencies = None | ||
1075 | 549 | |||
1076 | 550 | We can also set external dependencies for a single build. | ||
1077 | 551 | |||
1078 | 552 | >>> a_build.api_external_dependencies = ( | ||
1079 | 553 | ... u"deb http://user:pass@repository foo bar") | ||
1080 | 554 | >>> print_building_sources_list(a_build) | ||
1081 | 555 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
1082 | 556 | deb http://user:pass@repository foo bar | ||
1083 | 557 | deb http://archive.launchpad.dev/ubuntu hoary | ||
1084 | 558 | main restricted universe multiverse | ||
1085 | 559 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
1086 | 560 | main restricted universe multiverse | ||
1087 | 561 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
1088 | 562 | main restricted universe multiverse | ||
1089 | 563 | >>> a_build.api_external_dependencies = None | ||
1090 | 564 | |||
1091 | 565 | |||
1092 | 566 | == Build tools sources.list entries == | ||
1093 | 567 | |||
1094 | 568 | We can force an extra build tools line to be added to the sources.list, | ||
1095 | 569 | which is useful for specialised build types. | ||
1096 | 570 | |||
1097 | 571 | >>> for line in get_sources_list_for_building( | ||
1098 | 572 | ... a_build, a_build.distro_arch_series, | ||
1099 | 573 | ... a_build.source_package_release.name, | ||
1100 | 574 | ... tools_source="deb http://example.org %(series)s main"): | ||
1101 | 575 | ... print line | ||
1102 | 576 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
1103 | 577 | deb http://example.org hoary main | ||
1104 | 578 | deb http://archive.launchpad.dev/ubuntu hoary | ||
1105 | 579 | main restricted universe multiverse | ||
1106 | 580 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
1107 | 581 | main restricted universe multiverse | ||
1108 | 582 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
1109 | 583 | main restricted universe multiverse | ||
1110 | 584 | |||
1111 | 585 | If tools_source is badly formatted, we log the error but don't blow up. | ||
1112 | 586 | (Note the missing "s" at the end of "%(series)".) | ||
1113 | 587 | |||
1114 | 588 | >>> from lp.services.log.logger import BufferLogger | ||
1115 | 589 | >>> logger = BufferLogger() | ||
1116 | 590 | >>> for line in get_sources_list_for_building( | ||
1117 | 591 | ... a_build, a_build.distro_arch_series, | ||
1118 | 592 | ... a_build.source_package_release.name, | ||
1119 | 593 | ... tools_source="deb http://example.org %(series) main", | ||
1120 | 594 | ... logger=logger): | ||
1121 | 595 | ... print line | ||
1122 | 596 | deb http://ppa.launchpad.dev/cprov/ppa/ubuntu hoary main | ||
1123 | 597 | deb http://archive.launchpad.dev/ubuntu hoary | ||
1124 | 598 | main restricted universe multiverse | ||
1125 | 599 | deb http://archive.launchpad.dev/ubuntu hoary-security | ||
1126 | 600 | main restricted universe multiverse | ||
1127 | 601 | deb http://archive.launchpad.dev/ubuntu hoary-updates | ||
1128 | 602 | main restricted universe multiverse | ||
1129 | 603 | >>> print logger.getLogBuffer() | ||
1130 | 604 | ERROR Exception processing build tools sources.list entry: | ||
1131 | 605 | ... | ||
1132 | 606 | |||
1133 | 607 | |||
1134 | 608 | == Overlays == | ||
1135 | 609 | |||
1136 | 610 | An overlay distroseries is a derived distribution which works like a PPA. | ||
1137 | 611 | This means that the parent's details gets added to the sources.list passed to | ||
1138 | 612 | the builders. | ||
1139 | 613 | |||
1140 | 614 | >>> depdistro = factory.makeDistribution('depdistro', | ||
1141 | 615 | ... publish_base_url=u'http://archive.launchpad.dev/') | ||
1142 | 616 | >>> depseries = factory.makeDistroSeries( | ||
1143 | 617 | ... name='depseries', distribution=depdistro) | ||
1144 | 618 | >>> deparchseries = factory.makeDistroArchSeries( | ||
1145 | 619 | ... distroseries = depseries, architecturetag = 'i386') | ||
1146 | 620 | >>> test_publisher.addFakeChroots(depseries) | ||
1147 | 621 | >>> for component_name in ubuntu_components: | ||
1148 | 622 | ... component = getUtility(IComponentSet)[component_name] | ||
1149 | 623 | ... _ = factory.makeComponentSelection(depseries, component) | ||
1150 | 624 | >>> universe_component = getUtility(IComponentSet)['universe'] | ||
1151 | 625 | >>> dsp = factory.makeDistroSeriesParent( | ||
1152 | 626 | ... derived_series=hoary, parent_series=depseries, | ||
1153 | 627 | ... initialized=True, is_overlay=True, | ||
1154 | 628 | ... pocket=PackagePublishingPocket.SECURITY, | ||
1155 | 629 | ... component=universe_component) | ||
1156 | 630 | >>> pub_source = test_publisher.getPubSource( | ||
1157 | 631 | ... version='1.1', archive=hoary.main_archive) | ||
1158 | 632 | >>> [hoary_build] = pub_source.createMissingBuilds() | ||
1159 | 633 | >>> print_building_sources_list(hoary_build) | ||
1160 | 634 | deb http://archive.launchpad.dev/ubuntu hoary main | ||
1161 | 635 | deb http://archive.launchpad.dev/depdistro depseries main universe | ||
1162 | 636 | deb http://archive.launchpad.dev/depdistro depseries-security | ||
1163 | 637 | main universe | ||
1164 | 638 | 0 | ||
1165 | === modified file 'lib/lp/soyuz/interfaces/archive.py' | |||
1166 | --- lib/lp/soyuz/interfaces/archive.py 2016-11-14 19:55:07 +0000 | |||
1167 | +++ lib/lp/soyuz/interfaces/archive.py 2017-04-25 11:47:06 +0000 | |||
1168 | @@ -1,4 +1,4 @@ | |||
1170 | 1 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2017 Canonical Ltd. This software is licensed under the |
1171 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1172 | 3 | 3 | ||
1173 | 4 | """Archive interfaces.""" | 4 | """Archive interfaces.""" |
1174 | @@ -306,7 +306,7 @@ | |||
1175 | 306 | 306 | ||
1176 | 307 | def __init__(self, errors): | 307 | def __init__(self, errors): |
1177 | 308 | error_msg = 'Invalid external dependencies:\n%s\n' % '\n'.join(errors) | 308 | error_msg = 'Invalid external dependencies:\n%s\n' % '\n'.join(errors) |
1179 | 309 | super(Exception, self).__init__(self, error_msg) | 309 | super(Exception, self).__init__(error_msg) |
1180 | 310 | self.errors = errors | 310 | self.errors = errors |
1181 | 311 | 311 | ||
1182 | 312 | 312 | ||
1183 | 313 | 313 | ||
1184 | === modified file 'lib/lp/soyuz/tests/test_archive.py' | |||
1185 | --- lib/lp/soyuz/tests/test_archive.py 2016-11-07 16:42:23 +0000 | |||
1186 | +++ lib/lp/soyuz/tests/test_archive.py 2017-04-25 11:47:06 +0000 | |||
1187 | @@ -1,4 +1,4 @@ | |||
1189 | 1 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the | 1 | # Copyright 2009-2017 Canonical Ltd. This software is licensed under the |
1190 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1191 | 3 | 3 | ||
1192 | 4 | """Test Archive features.""" | 4 | """Test Archive features.""" |
1193 | @@ -78,6 +78,7 @@ | |||
1194 | 78 | DuplicateTokenName, | 78 | DuplicateTokenName, |
1195 | 79 | IArchiveSet, | 79 | IArchiveSet, |
1196 | 80 | InsufficientUploadRights, | 80 | InsufficientUploadRights, |
1197 | 81 | InvalidExternalDependencies, | ||
1198 | 81 | InvalidPocketForPartnerArchive, | 82 | InvalidPocketForPartnerArchive, |
1199 | 82 | InvalidPocketForPPA, | 83 | InvalidPocketForPPA, |
1200 | 83 | NAMED_AUTH_TOKEN_FEATURE_FLAG, | 84 | NAMED_AUTH_TOKEN_FEATURE_FLAG, |
1201 | @@ -1767,6 +1768,18 @@ | |||
1202 | 1767 | "person-name-.*/dependency/ubuntu distroseries-.* main") | 1768 | "person-name-.*/dependency/ubuntu distroseries-.* main") |
1203 | 1768 | self.assertThat(sources_list[0], matches) | 1769 | self.assertThat(sources_list[0], matches) |
1204 | 1769 | 1770 | ||
1205 | 1771 | def test_invalid_external_dependencies(self): | ||
1206 | 1772 | """Trying to set invalid external dependencies raises an exception.""" | ||
1207 | 1773 | ppa = self.factory.makeArchive() | ||
1208 | 1774 | self.assertRaisesWithContent( | ||
1209 | 1775 | InvalidExternalDependencies, | ||
1210 | 1776 | "Invalid external dependencies:\n" | ||
1211 | 1777 | "Malformed format string here --> %(series): " | ||
1212 | 1778 | "Must start with 'deb'\n" | ||
1213 | 1779 | "Malformed format string here --> %(series): Invalid URL\n", | ||
1214 | 1780 | setattr, ppa, "external_dependencies", | ||
1215 | 1781 | "Malformed format string here --> %(series)") | ||
1216 | 1782 | |||
1217 | 1770 | 1783 | ||
1218 | 1771 | class TestFindDepCandidates(TestCaseWithFactory): | 1784 | class TestFindDepCandidates(TestCaseWithFactory): |
1219 | 1772 | """Tests for Archive.findDepCandidates.""" | 1785 | """Tests for Archive.findDepCandidates.""" |
1220 | 1773 | 1786 | ||
1221 | === modified file 'lib/lp/testing/factory.py' | |||
1222 | --- lib/lp/testing/factory.py 2016-12-02 12:04:11 +0000 | |||
1223 | +++ lib/lp/testing/factory.py 2017-04-25 11:47:06 +0000 | |||
1224 | @@ -2,7 +2,7 @@ | |||
1225 | 2 | # NOTE: The first line above must stay first; do not move the copyright | 2 | # NOTE: The first line above must stay first; do not move the copyright |
1226 | 3 | # notice to the top. See http://www.python.org/dev/peps/pep-0263/. | 3 | # notice to the top. See http://www.python.org/dev/peps/pep-0263/. |
1227 | 4 | # | 4 | # |
1229 | 5 | # Copyright 2009-2016 Canonical Ltd. This software is licensed under the | 5 | # Copyright 2009-2017 Canonical Ltd. This software is licensed under the |
1230 | 6 | # GNU Affero General Public License version 3 (see the file LICENSE). | 6 | # GNU Affero General Public License version 3 (see the file LICENSE). |
1231 | 7 | 7 | ||
1232 | 8 | """Testing infrastructure for the Launchpad application. | 8 | """Testing infrastructure for the Launchpad application. |
1233 | @@ -268,7 +268,10 @@ | |||
1234 | 268 | ) | 268 | ) |
1235 | 269 | from lp.services.oauth.interfaces import IOAuthConsumerSet | 269 | from lp.services.oauth.interfaces import IOAuthConsumerSet |
1236 | 270 | from lp.services.openid.model.openididentifier import OpenIdIdentifier | 270 | from lp.services.openid.model.openididentifier import OpenIdIdentifier |
1238 | 271 | from lp.services.propertycache import clear_property_cache | 271 | from lp.services.propertycache import ( |
1239 | 272 | clear_property_cache, | ||
1240 | 273 | get_property_cache, | ||
1241 | 274 | ) | ||
1242 | 272 | from lp.services.temporaryblobstorage.interfaces import ( | 275 | from lp.services.temporaryblobstorage.interfaces import ( |
1243 | 273 | ITemporaryStorageManager, | 276 | ITemporaryStorageManager, |
1244 | 274 | ) | 277 | ) |
1245 | @@ -2832,8 +2835,10 @@ | |||
1246 | 2832 | if not IComponent.providedBy(component): | 2835 | if not IComponent.providedBy(component): |
1247 | 2833 | component = self.makeComponent(component) | 2836 | component = self.makeComponent(component) |
1248 | 2834 | 2837 | ||
1250 | 2835 | return ComponentSelection( | 2838 | selection = ComponentSelection( |
1251 | 2836 | distroseries=distroseries, component=component) | 2839 | distroseries=distroseries, component=component) |
1252 | 2840 | del get_property_cache(distroseries).components | ||
1253 | 2841 | return selection | ||
1254 | 2837 | 2842 | ||
1255 | 2838 | def makeArchive(self, distribution=None, owner=None, name=None, | 2843 | def makeArchive(self, distribution=None, owner=None, name=None, |
1256 | 2839 | purpose=None, enabled=True, private=False, | 2844 | purpose=None, enabled=True, private=False, |