Merge lp:~james-w/launchpad/copy-archive-package-sets into lp:launchpad/db-devel
- copy-archive-package-sets
- Merge into db-devel
Status: | Merged |
---|---|
Approved by: | Graham Binns |
Approved revision: | no longer in the source branch. |
Merged at revision: | 9495 |
Proposed branch: | lp:~james-w/launchpad/copy-archive-package-sets |
Merge into: | lp:launchpad/db-devel |
Prerequisite: | lp:~james-w/launchpad/copy-archive-test-refactor |
Diff against target: |
446 lines (+212/-15) 5 files modified
lib/lp/soyuz/adapters/packagelocation.py (+26/-4) lib/lp/soyuz/adapters/tests/test_packagelocation.py (+54/-2) lib/lp/soyuz/model/packagecloner.py (+13/-1) lib/lp/soyuz/scripts/populate_archive.py (+17/-6) lib/lp/soyuz/scripts/tests/test_populatearchive.py (+102/-2) |
To merge this branch: | bzr merge lp:~james-w/launchpad/copy-archive-package-sets |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Graham Binns (community) | code | Approve | |
Review via email: mp+28165@code.launchpad.net |
Commit message
--package-set can now be passed to populate_archive to limit the packages copied.
Description of the change
Summary
We want to be able to create copy archives that aren't the full archive.
A way to subset the archive in LP is by packageset, so we make use of that.
Proposed fix
This merge proposal adds a --package-set option to populate_
which can be specified multiple times, and then only copies the packages
contained within the named sets.
Pre-implementation notes
Spoke briefly with Julian.
Implementation details
First PackageLocation was modified to store a list of package sets for the
source. build_package_
on names.
We then hooked that up to the --package-set option to get the list of package
sets the user wants.
The final step is to hook that in to the query that copies the sources. Here we
take care to include the transitive closure of packages across the DAG of package
sets.
Tests
You can run them with
./bin/test -s lp.soyuz.scripts -m test_populatear
and
./bin/test -s lp.soyuz.adapters
Demo and Q/A
None.
lint
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files:
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
== Pyflakes notices ==
lib/lp/
112: local variable 'ignore_this' is assigned to but never used
287: local variable 'ignore_result' is assigned to but never used
Preview Diff
1 | === modified file 'lib/lp/soyuz/adapters/packagelocation.py' | |||
2 | --- lib/lp/soyuz/adapters/packagelocation.py 2009-08-28 06:39:38 +0000 | |||
3 | +++ lib/lp/soyuz/adapters/packagelocation.py 2010-06-22 12:51:37 +0000 | |||
4 | @@ -28,22 +28,25 @@ | |||
5 | 28 | distroseries = None | 28 | distroseries = None |
6 | 29 | pocket = None | 29 | pocket = None |
7 | 30 | component = None | 30 | component = None |
8 | 31 | packagesets = None | ||
9 | 31 | 32 | ||
10 | 32 | def __init__(self, archive, distribution, distroseries, pocket, | 33 | def __init__(self, archive, distribution, distroseries, pocket, |
12 | 33 | component=None): | 34 | component=None, packagesets=None): |
13 | 34 | """Initialize the PackageLocation from the given parameters.""" | 35 | """Initialize the PackageLocation from the given parameters.""" |
14 | 35 | self.archive = archive | 36 | self.archive = archive |
15 | 36 | self.distribution = distribution | 37 | self.distribution = distribution |
16 | 37 | self.distroseries = distroseries | 38 | self.distroseries = distroseries |
17 | 38 | self.pocket = pocket | 39 | self.pocket = pocket |
18 | 39 | self.component = component | 40 | self.component = component |
19 | 41 | self.packagesets = packagesets or [] | ||
20 | 40 | 42 | ||
21 | 41 | def __eq__(self, other): | 43 | def __eq__(self, other): |
22 | 42 | if (self.distribution == other.distribution and | 44 | if (self.distribution == other.distribution and |
23 | 43 | self.archive == other.archive and | 45 | self.archive == other.archive and |
24 | 44 | self.distroseries == other.distroseries and | 46 | self.distroseries == other.distroseries and |
25 | 45 | self.component == other.component and | 47 | self.component == other.component and |
27 | 46 | self.pocket == other.pocket): | 48 | self.pocket == other.pocket and |
28 | 49 | self.packagesets == other.packagesets): | ||
29 | 47 | return True | 50 | return True |
30 | 48 | return False | 51 | return False |
31 | 49 | 52 | ||
32 | @@ -63,6 +66,10 @@ | |||
33 | 63 | if self.component is not None: | 66 | if self.component is not None: |
34 | 64 | result += ' (%s)' % self.component.name | 67 | result += ' (%s)' % self.component.name |
35 | 65 | 68 | ||
36 | 69 | if len(self.packagesets) > 0: | ||
37 | 70 | result += ' [%s]' % ( | ||
38 | 71 | ", ".join([str(p.name) for p in self.packagesets]),) | ||
39 | 72 | |||
40 | 66 | return result | 73 | return result |
41 | 67 | 74 | ||
42 | 68 | 75 | ||
43 | @@ -71,7 +78,8 @@ | |||
44 | 71 | 78 | ||
45 | 72 | 79 | ||
46 | 73 | def build_package_location(distribution_name, suite=None, purpose=None, | 80 | def build_package_location(distribution_name, suite=None, purpose=None, |
48 | 74 | person_name=None, archive_name=None): | 81 | person_name=None, archive_name=None, |
49 | 82 | packageset_names=None): | ||
50 | 75 | """Convenience function to build PackageLocation objects.""" | 83 | """Convenience function to build PackageLocation objects.""" |
51 | 76 | 84 | ||
52 | 77 | # XXX kiko 2007-10-24: | 85 | # XXX kiko 2007-10-24: |
53 | @@ -87,6 +95,7 @@ | |||
54 | 87 | # Avoid circular imports. | 95 | # Avoid circular imports. |
55 | 88 | from lp.registry.interfaces.distribution import IDistributionSet | 96 | from lp.registry.interfaces.distribution import IDistributionSet |
56 | 89 | from lp.soyuz.interfaces.archive import ArchivePurpose, IArchiveSet | 97 | from lp.soyuz.interfaces.archive import ArchivePurpose, IArchiveSet |
57 | 98 | from lp.soyuz.interfaces.packageset import IPackagesetSet | ||
58 | 90 | from lp.registry.interfaces.pocket import PackagePublishingPocket | 99 | from lp.registry.interfaces.pocket import PackagePublishingPocket |
59 | 91 | 100 | ||
60 | 92 | try: | 101 | try: |
61 | @@ -144,4 +153,17 @@ | |||
62 | 144 | distroseries = distribution.currentseries | 153 | distroseries = distribution.currentseries |
63 | 145 | pocket = PackagePublishingPocket.RELEASE | 154 | pocket = PackagePublishingPocket.RELEASE |
64 | 146 | 155 | ||
66 | 147 | return PackageLocation(archive, distribution, distroseries, pocket) | 156 | packagesets = [] |
67 | 157 | if packageset_names: | ||
68 | 158 | packageset_set = getUtility(IPackagesetSet) | ||
69 | 159 | for packageset_name in packageset_names: | ||
70 | 160 | try: | ||
71 | 161 | packageset = packageset_set.getByName( | ||
72 | 162 | packageset_name, distroseries=distroseries) | ||
73 | 163 | except NotFoundError, err: | ||
74 | 164 | raise PackageLocationError( | ||
75 | 165 | "Could not find packageset %s" % err) | ||
76 | 166 | packagesets.append(packageset) | ||
77 | 167 | |||
78 | 168 | return PackageLocation(archive, distribution, distroseries, pocket, | ||
79 | 169 | packagesets=packagesets) | ||
80 | 148 | 170 | ||
81 | === added file 'lib/lp/soyuz/adapters/tests/__init__.py' | |||
82 | === modified file 'lib/lp/soyuz/adapters/tests/test_packagelocation.py' | |||
83 | --- lib/lp/soyuz/adapters/tests/test_packagelocation.py 2009-06-25 04:06:00 +0000 | |||
84 | +++ lib/lp/soyuz/adapters/tests/test_packagelocation.py 2010-06-22 12:51:37 +0000 | |||
85 | @@ -20,10 +20,11 @@ | |||
86 | 20 | 20 | ||
87 | 21 | def getPackageLocation(self, distribution_name='ubuntu', suite=None, | 21 | def getPackageLocation(self, distribution_name='ubuntu', suite=None, |
88 | 22 | purpose=None, person_name=None, | 22 | purpose=None, person_name=None, |
90 | 23 | archive_name=None): | 23 | archive_name=None, packageset_names=None): |
91 | 24 | """Use a helper method to setup a `PackageLocation` object.""" | 24 | """Use a helper method to setup a `PackageLocation` object.""" |
92 | 25 | return build_package_location( | 25 | return build_package_location( |
94 | 26 | distribution_name, suite, purpose, person_name, archive_name) | 26 | distribution_name, suite, purpose, person_name, archive_name, |
95 | 27 | packageset_names=packageset_names) | ||
96 | 27 | 28 | ||
97 | 28 | def testSetupLocationForCOPY(self): | 29 | def testSetupLocationForCOPY(self): |
98 | 29 | """`PackageLocation` for COPY archives.""" | 30 | """`PackageLocation` for COPY archives.""" |
99 | @@ -45,6 +46,7 @@ | |||
100 | 45 | self.assertEqual(location.pocket.name, 'RELEASE') | 46 | self.assertEqual(location.pocket.name, 'RELEASE') |
101 | 46 | self.assertEqual(location.archive.displayname, | 47 | self.assertEqual(location.archive.displayname, |
102 | 47 | 'Copy archive now-comes-the-mystery for Mysteryman') | 48 | 'Copy archive now-comes-the-mystery for Mysteryman') |
103 | 49 | self.assertEqual([], location.packagesets) | ||
104 | 48 | 50 | ||
105 | 49 | def testSetupLocationForPRIMARY(self): | 51 | def testSetupLocationForPRIMARY(self): |
106 | 50 | """`PackageLocation` for PRIMARY archives.""" | 52 | """`PackageLocation` for PRIMARY archives.""" |
107 | @@ -54,6 +56,7 @@ | |||
108 | 54 | self.assertEqual(location.pocket.name, 'RELEASE') | 56 | self.assertEqual(location.pocket.name, 'RELEASE') |
109 | 55 | self.assertEqual(location.archive.displayname, | 57 | self.assertEqual(location.archive.displayname, |
110 | 56 | 'Primary Archive for Ubuntu Linux') | 58 | 'Primary Archive for Ubuntu Linux') |
111 | 59 | self.assertEqual([], location.packagesets) | ||
112 | 57 | 60 | ||
113 | 58 | def testSetupLocationForPPA(self): | 61 | def testSetupLocationForPPA(self): |
114 | 59 | """`PackageLocation` for PPA archives.""" | 62 | """`PackageLocation` for PPA archives.""" |
115 | @@ -65,6 +68,7 @@ | |||
116 | 65 | self.assertEqual(location.pocket.name, 'RELEASE') | 68 | self.assertEqual(location.pocket.name, 'RELEASE') |
117 | 66 | self.assertEqual(location.archive.displayname, | 69 | self.assertEqual(location.archive.displayname, |
118 | 67 | 'PPA for Celso Providelo') | 70 | 'PPA for Celso Providelo') |
119 | 71 | self.assertEqual([], location.packagesets) | ||
120 | 68 | 72 | ||
121 | 69 | def testSetupLocationForPARTNER(self): | 73 | def testSetupLocationForPARTNER(self): |
122 | 70 | """`PackageLocation` for PARTNER archives.""" | 74 | """`PackageLocation` for PARTNER archives.""" |
123 | @@ -74,6 +78,16 @@ | |||
124 | 74 | self.assertEqual(location.pocket.name, 'RELEASE') | 78 | self.assertEqual(location.pocket.name, 'RELEASE') |
125 | 75 | self.assertEqual(location.archive.displayname, | 79 | self.assertEqual(location.archive.displayname, |
126 | 76 | 'Partner Archive for Ubuntu Linux') | 80 | 'Partner Archive for Ubuntu Linux') |
127 | 81 | self.assertEqual([], location.packagesets) | ||
128 | 82 | |||
129 | 83 | def testSetupLocationWithPackagesets(self): | ||
130 | 84 | packageset_name1 = u"foo-packageset" | ||
131 | 85 | packageset_name2 = u"bar-packageset" | ||
132 | 86 | packageset1 = self.factory.makePackageset(name=packageset_name1) | ||
133 | 87 | packageset2 = self.factory.makePackageset(name=packageset_name2) | ||
134 | 88 | location = self.getPackageLocation( | ||
135 | 89 | packageset_names=[packageset_name1, packageset_name2]) | ||
136 | 90 | self.assertEqual([packageset1, packageset2], location.packagesets) | ||
137 | 77 | 91 | ||
138 | 78 | def testSetupLocationUnknownDistribution(self): | 92 | def testSetupLocationUnknownDistribution(self): |
139 | 79 | """`PackageLocationError` is raised on unknown distribution.""" | 93 | """`PackageLocationError` is raised on unknown distribution.""" |
140 | @@ -115,6 +129,24 @@ | |||
141 | 115 | distribution_name='debian', | 129 | distribution_name='debian', |
142 | 116 | purpose=ArchivePurpose.PARTNER) | 130 | purpose=ArchivePurpose.PARTNER) |
143 | 117 | 131 | ||
144 | 132 | def test_build_package_location_when_packageset_unknown(self): | ||
145 | 133 | """`PackageLocationError` is raised on unknown packageset.""" | ||
146 | 134 | self.assertRaises( | ||
147 | 135 | PackageLocationError, | ||
148 | 136 | self.getPackageLocation, | ||
149 | 137 | distribution_name='debian', | ||
150 | 138 | packageset_names=[u"unknown"]) | ||
151 | 139 | |||
152 | 140 | def test_build_package_location_when_one_packageset_unknown(self): | ||
153 | 141 | """Test that with one of two packagesets unknown.""" | ||
154 | 142 | packageset_name = u"foo-packageset" | ||
155 | 143 | self.factory.makePackageset(name=packageset_name) | ||
156 | 144 | self.assertRaises( | ||
157 | 145 | PackageLocationError, | ||
158 | 146 | self.getPackageLocation, | ||
159 | 147 | distribution_name='debian', | ||
160 | 148 | packageset_names=[packageset_name, u"unknown"]) | ||
161 | 149 | |||
162 | 118 | def testSetupLocationPPANotMatchingDistribution(self): | 150 | def testSetupLocationPPANotMatchingDistribution(self): |
163 | 119 | """`PackageLocationError` is raised when PPA does not match the | 151 | """`PackageLocationError` is raised when PPA does not match the |
164 | 120 | distribution.""" | 152 | distribution.""" |
165 | @@ -167,6 +199,18 @@ | |||
166 | 167 | distribution_name='ubuntu', purpose=ArchivePurpose.PARTNER) | 199 | distribution_name='ubuntu', purpose=ArchivePurpose.PARTNER) |
167 | 168 | self.assertNotEqual(location_ubuntu_partner, location_cprov_ppa) | 200 | self.assertNotEqual(location_ubuntu_partner, location_cprov_ppa) |
168 | 169 | 201 | ||
169 | 202 | def testComparePackagesets(self): | ||
170 | 203 | location_ubuntu_hoary = self.getPackageLocation() | ||
171 | 204 | location_ubuntu_hoary_again = self.getPackageLocation() | ||
172 | 205 | packageset = self.factory.makePackageset() | ||
173 | 206 | location_ubuntu_hoary.packagesets = [packageset] | ||
174 | 207 | self.assertNotEqual( | ||
175 | 208 | location_ubuntu_hoary, location_ubuntu_hoary_again) | ||
176 | 209 | |||
177 | 210 | location_ubuntu_hoary_again.packagesets = [packageset] | ||
178 | 211 | self.assertEqual( | ||
179 | 212 | location_ubuntu_hoary, location_ubuntu_hoary_again) | ||
180 | 213 | |||
181 | 170 | def testRepresentation(self): | 214 | def testRepresentation(self): |
182 | 171 | """Check if PackageLocation is represented correctly.""" | 215 | """Check if PackageLocation is represented correctly.""" |
183 | 172 | location_ubuntu_hoary = self.getPackageLocation() | 216 | location_ubuntu_hoary = self.getPackageLocation() |
184 | @@ -204,6 +248,14 @@ | |||
185 | 204 | str(location_ubuntu_partner), | 248 | str(location_ubuntu_partner), |
186 | 205 | 'Partner Archive for Ubuntu Linux: hoary-RELEASE') | 249 | 'Partner Archive for Ubuntu Linux: hoary-RELEASE') |
187 | 206 | 250 | ||
188 | 251 | self.factory.makePackageset(name=u"foo-packageset") | ||
189 | 252 | location_ubuntu_packageset = self.getPackageLocation( | ||
190 | 253 | packageset_names=[u"foo-packageset"]) | ||
191 | 254 | self.assertEqual( | ||
192 | 255 | str(location_ubuntu_packageset), | ||
193 | 256 | 'Primary Archive for Ubuntu Linux: ' | ||
194 | 257 | 'hoary-RELEASE [foo-packageset]') | ||
195 | 258 | |||
196 | 207 | 259 | ||
197 | 208 | def test_suite(): | 260 | def test_suite(): |
198 | 209 | return unittest.TestLoader().loadTestsFromName(__name__) | 261 | return unittest.TestLoader().loadTestsFromName(__name__) |
199 | 210 | 262 | ||
200 | === modified file 'lib/lp/soyuz/model/packagecloner.py' | |||
201 | --- lib/lp/soyuz/model/packagecloner.py 2010-01-12 08:36:58 +0000 | |||
202 | +++ lib/lp/soyuz/model/packagecloner.py 2010-06-22 12:51:37 +0000 | |||
203 | @@ -305,7 +305,7 @@ | |||
204 | 305 | to be copied. | 305 | to be copied. |
205 | 306 | """ | 306 | """ |
206 | 307 | store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) | 307 | store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
208 | 308 | store.execute(''' | 308 | query = (''' |
209 | 309 | INSERT INTO SourcePackagePublishingHistory ( | 309 | INSERT INTO SourcePackagePublishingHistory ( |
210 | 310 | sourcepackagerelease, distroseries, status, component, | 310 | sourcepackagerelease, distroseries, status, component, |
211 | 311 | section, archive, datecreated, datepublished, pocket) | 311 | section, archive, datecreated, datepublished, pocket) |
212 | @@ -322,6 +322,18 @@ | |||
213 | 322 | PackagePublishingStatus.PENDING, | 322 | PackagePublishingStatus.PENDING, |
214 | 323 | PackagePublishingStatus.PUBLISHED, | 323 | PackagePublishingStatus.PUBLISHED, |
215 | 324 | origin.pocket, origin.archive)) | 324 | origin.pocket, origin.archive)) |
216 | 325 | if origin.packagesets: | ||
217 | 326 | query += '''AND spph.sourcepackagerelease IN | ||
218 | 327 | (SELECT spr.id | ||
219 | 328 | FROM SourcePackageRelease AS spr, | ||
220 | 329 | packagesetsources AS pss, | ||
221 | 330 | flatpackagesetinclusion AS fpsi | ||
222 | 331 | WHERE spr.sourcepackagename | ||
223 | 332 | = pss.sourcepackagename | ||
224 | 333 | AND pss.packageset = fpsi.child | ||
225 | 334 | AND fpsi.parent in %s) | ||
226 | 335 | ''' % sqlvalues([p.id for p in origin.packagesets]) | ||
227 | 336 | store.execute(query) | ||
228 | 325 | 337 | ||
229 | 326 | def packageSetDiff(self, origin, destination, logger=None): | 338 | def packageSetDiff(self, origin, destination, logger=None): |
230 | 327 | """Please see `IPackageCloner`.""" | 339 | """Please see `IPackageCloner`.""" |
231 | 328 | 340 | ||
232 | === modified file 'lib/lp/soyuz/scripts/populate_archive.py' | |||
233 | --- lib/lp/soyuz/scripts/populate_archive.py 2010-06-22 12:51:34 +0000 | |||
234 | +++ lib/lp/soyuz/scripts/populate_archive.py 2010-06-22 12:51:37 +0000 | |||
235 | @@ -53,7 +53,7 @@ | |||
236 | 53 | self, from_archive, from_distribution, from_suite, from_user, | 53 | self, from_archive, from_distribution, from_suite, from_user, |
237 | 54 | component, to_distribution, to_suite, to_archive, to_user, reason, | 54 | component, to_distribution, to_suite, to_archive, to_user, reason, |
238 | 55 | include_binaries, arch_tags, merge_copy_flag, | 55 | include_binaries, arch_tags, merge_copy_flag, |
240 | 56 | packageset_delta_flag): | 56 | packageset_delta_flag, packageset_tags): |
241 | 57 | """Create archive, populate it with packages and builds. | 57 | """Create archive, populate it with packages and builds. |
242 | 58 | 58 | ||
243 | 59 | Please note: if a component was specified for the origin then the | 59 | Please note: if a component was specified for the origin then the |
244 | @@ -79,6 +79,9 @@ | |||
245 | 79 | existing copy archive. | 79 | existing copy archive. |
246 | 80 | :param packageset_delta_flag: only show packages that are fresher or | 80 | :param packageset_delta_flag: only show packages that are fresher or |
247 | 81 | new in the origin archive. Do not copy anything. | 81 | new in the origin archive. Do not copy anything. |
248 | 82 | |||
249 | 83 | :param packageset_tags: list of packagesets to limit the packages | ||
250 | 84 | copied to. | ||
251 | 82 | """ | 85 | """ |
252 | 83 | # Avoid circular imports. | 86 | # Avoid circular imports. |
253 | 84 | from lp.registry.interfaces.person import IPersonSet | 87 | from lp.registry.interfaces.person import IPersonSet |
254 | @@ -108,13 +111,14 @@ | |||
255 | 108 | for proc_family in proc_families: | 111 | for proc_family in proc_families: |
256 | 109 | ignore_this = aa_set.new(archive, proc_family) | 112 | ignore_this = aa_set.new(archive, proc_family) |
257 | 110 | 113 | ||
259 | 111 | def build_location(distro, suite, component): | 114 | def build_location(distro, suite, component, packageset_names=None): |
260 | 112 | """Build and return package location.""" | 115 | """Build and return package location.""" |
262 | 113 | location = build_package_location(distro, suite=suite) | 116 | location = build_package_location( |
263 | 117 | distro, suite=suite, packageset_names=packageset_names) | ||
264 | 114 | if component is not None: | 118 | if component is not None: |
265 | 115 | try: | 119 | try: |
266 | 116 | the_component = getUtility(IComponentSet)[component] | 120 | the_component = getUtility(IComponentSet)[component] |
268 | 117 | except NotFoundError, e: | 121 | except NotFoundError: |
269 | 118 | raise SoyuzScriptError( | 122 | raise SoyuzScriptError( |
270 | 119 | "Invalid component name: '%s'" % component) | 123 | "Invalid component name: '%s'" % component) |
271 | 120 | location.component = the_component | 124 | location.component = the_component |
272 | @@ -122,7 +126,9 @@ | |||
273 | 122 | 126 | ||
274 | 123 | archive_set = getUtility(IArchiveSet) | 127 | archive_set = getUtility(IArchiveSet) |
275 | 124 | # Build the origin package location. | 128 | # Build the origin package location. |
277 | 125 | the_origin = build_location(from_distribution, from_suite, component) | 129 | the_origin = build_location( |
278 | 130 | from_distribution, from_suite, component, | ||
279 | 131 | packageset_names=packageset_tags) | ||
280 | 126 | 132 | ||
281 | 127 | # Use a non-PPA(!) origin archive if specified and existent. | 133 | # Use a non-PPA(!) origin archive if specified and existent. |
282 | 128 | if from_archive is not None and from_user is None: | 134 | if from_archive is not None and from_user is None: |
283 | @@ -315,7 +321,7 @@ | |||
284 | 315 | opts.from_user, opts.component, opts.to_distribution, | 321 | opts.from_user, opts.component, opts.to_distribution, |
285 | 316 | opts.to_suite, opts.to_archive, opts.to_user, opts.reason, | 322 | opts.to_suite, opts.to_archive, opts.to_user, opts.reason, |
286 | 317 | opts.include_binaries, opts.arch_tags, opts.merge_copy_flag, | 323 | opts.include_binaries, opts.arch_tags, opts.merge_copy_flag, |
288 | 318 | opts.packageset_delta_flag) | 324 | opts.packageset_delta_flag, opts.packageset_tags) |
289 | 319 | 325 | ||
290 | 320 | def add_my_options(self): | 326 | def add_my_options(self): |
291 | 321 | """Parse command line arguments for copy archive creation/population. | 327 | """Parse command line arguments for copy archive creation/population. |
292 | @@ -379,6 +385,11 @@ | |||
293 | 379 | 'Only show packages that are fresher or new in origin ' | 385 | 'Only show packages that are fresher or new in origin ' |
294 | 380 | 'archive. Destination archive must exist already.')) | 386 | 'archive. Destination archive must exist already.')) |
295 | 381 | 387 | ||
296 | 388 | self.parser.add_option( | ||
297 | 389 | "--package-set", dest="packageset_tags", action="append", | ||
298 | 390 | help=( | ||
299 | 391 | 'Limit to copying packages in the selected packagesets.')) | ||
300 | 392 | |||
301 | 382 | def _createMissingBuilds( | 393 | def _createMissingBuilds( |
302 | 383 | self, distroseries, archive, proc_families): | 394 | self, distroseries, archive, proc_families): |
303 | 384 | """Create builds for all cloned source packages. | 395 | """Create builds for all cloned source packages. |
304 | 385 | 396 | ||
305 | === modified file 'lib/lp/soyuz/scripts/tests/test_populatearchive.py' | |||
306 | --- lib/lp/soyuz/scripts/tests/test_populatearchive.py 2010-06-22 12:51:34 +0000 | |||
307 | +++ lib/lp/soyuz/scripts/tests/test_populatearchive.py 2010-06-22 12:51:37 +0000 | |||
308 | @@ -206,7 +206,7 @@ | |||
309 | 206 | def getScript(self, test_args=None): | 206 | def getScript(self, test_args=None): |
310 | 207 | """Return an ArchivePopulator instance.""" | 207 | """Return an ArchivePopulator instance.""" |
311 | 208 | if test_args is None: | 208 | if test_args is None: |
313 | 209 | test_args = [] | 209 | test_args = [] |
314 | 210 | script = ArchivePopulator("test copy archives", test_args=test_args) | 210 | script = ArchivePopulator("test copy archives", test_args=test_args) |
315 | 211 | script.logger = QuietFakeLogger() | 211 | script.logger = QuietFakeLogger() |
316 | 212 | script.txn = self.layer.txn | 212 | script.txn = self.layer.txn |
317 | @@ -214,7 +214,7 @@ | |||
318 | 214 | 214 | ||
319 | 215 | def copyArchive(self, distroseries, archive_name, owner, | 215 | def copyArchive(self, distroseries, archive_name, owner, |
320 | 216 | architectures=None, component="main", from_user=None, | 216 | architectures=None, component="main", from_user=None, |
322 | 217 | from_archive=None): | 217 | from_archive=None, packageset_names=None): |
323 | 218 | """Run the copy-archive script.""" | 218 | """Run the copy-archive script.""" |
324 | 219 | extra_args = [ | 219 | extra_args = [ |
325 | 220 | '--from-distribution', distroseries.distribution.name, | 220 | '--from-distribution', distroseries.distribution.name, |
326 | @@ -240,6 +240,12 @@ | |||
327 | 240 | for architecture in architectures: | 240 | for architecture in architectures: |
328 | 241 | extra_args.extend(['-a', architecture]) | 241 | extra_args.extend(['-a', architecture]) |
329 | 242 | 242 | ||
330 | 243 | if packageset_names is None: | ||
331 | 244 | packageset_names = [] | ||
332 | 245 | |||
333 | 246 | for packageset_name in packageset_names: | ||
334 | 247 | extra_args.extend(['--package-set', packageset_name]) | ||
335 | 248 | |||
336 | 243 | script = self.getScript(test_args=extra_args) | 249 | script = self.getScript(test_args=extra_args) |
337 | 244 | script.mainTask() | 250 | script.mainTask() |
338 | 245 | 251 | ||
339 | @@ -521,6 +527,86 @@ | |||
340 | 521 | component="main") | 527 | component="main") |
341 | 522 | self.checkBuilds(copy_archive, package_infos) | 528 | self.checkBuilds(copy_archive, package_infos) |
342 | 523 | 529 | ||
343 | 530 | def testCopyArchiveSubsetsBasedOnPackageset(self): | ||
344 | 531 | """Test that --package-set limits the sources copied.""" | ||
345 | 532 | package_infos = [ | ||
346 | 533 | PackageInfo( | ||
347 | 534 | "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), | ||
348 | 535 | PackageInfo( | ||
349 | 536 | "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), | ||
350 | 537 | ] | ||
351 | 538 | owner = self.createTargetOwner() | ||
352 | 539 | distroseries = self.createSourceDistribution(package_infos) | ||
353 | 540 | packageset_name = u"apt-packageset" | ||
354 | 541 | spn = self.factory.getOrMakeSourcePackageName(name="apt") | ||
355 | 542 | self.factory.makePackageset( | ||
356 | 543 | name=packageset_name, distroseries=distroseries, packages=(spn,)) | ||
357 | 544 | archive_name = self.getTargetArchiveName(distroseries.distribution) | ||
358 | 545 | copy_archive = self.copyArchive( | ||
359 | 546 | distroseries, archive_name, owner, | ||
360 | 547 | packageset_names=[packageset_name]) | ||
361 | 548 | self.checkCopiedSources( | ||
362 | 549 | copy_archive, distroseries, [package_infos[1]]) | ||
363 | 550 | |||
364 | 551 | def testCopyArchiveUnionsPackagesets(self): | ||
365 | 552 | """Test that package sets are unioned when copying archives.""" | ||
366 | 553 | package_infos = [ | ||
367 | 554 | PackageInfo( | ||
368 | 555 | "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), | ||
369 | 556 | PackageInfo( | ||
370 | 557 | "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), | ||
371 | 558 | PackageInfo( | ||
372 | 559 | "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED), | ||
373 | 560 | ] | ||
374 | 561 | owner = self.createTargetOwner() | ||
375 | 562 | distroseries = self.createSourceDistribution(package_infos) | ||
376 | 563 | apt_packageset_name = u"apt-packageset" | ||
377 | 564 | apt_spn = self.factory.getOrMakeSourcePackageName(name="apt") | ||
378 | 565 | gcc_packageset_name = u"gcc-packageset" | ||
379 | 566 | gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc") | ||
380 | 567 | self.factory.makePackageset( | ||
381 | 568 | name=apt_packageset_name, distroseries=distroseries, | ||
382 | 569 | packages=(apt_spn,)) | ||
383 | 570 | self.factory.makePackageset( | ||
384 | 571 | name=gcc_packageset_name, distroseries=distroseries, | ||
385 | 572 | packages=(gcc_spn,)) | ||
386 | 573 | archive_name = self.getTargetArchiveName(distroseries.distribution) | ||
387 | 574 | copy_archive = self.copyArchive( | ||
388 | 575 | distroseries, archive_name, owner, | ||
389 | 576 | packageset_names=[apt_packageset_name, gcc_packageset_name]) | ||
390 | 577 | self.checkCopiedSources( | ||
391 | 578 | copy_archive, distroseries, package_infos[1:]) | ||
392 | 579 | |||
393 | 580 | def testCopyArchiveRecursivelyCopiesPackagesets(self): | ||
394 | 581 | """Test that package set copies include subsets.""" | ||
395 | 582 | package_infos = [ | ||
396 | 583 | PackageInfo( | ||
397 | 584 | "bzr", "2.1", status=PackagePublishingStatus.PUBLISHED), | ||
398 | 585 | PackageInfo( | ||
399 | 586 | "apt", "2.2", status=PackagePublishingStatus.PUBLISHED), | ||
400 | 587 | PackageInfo( | ||
401 | 588 | "gcc", "4.5", status=PackagePublishingStatus.PUBLISHED), | ||
402 | 589 | ] | ||
403 | 590 | owner = self.createTargetOwner() | ||
404 | 591 | distroseries = self.createSourceDistribution(package_infos) | ||
405 | 592 | apt_packageset_name = u"apt-packageset" | ||
406 | 593 | apt_spn = self.factory.getOrMakeSourcePackageName(name="apt") | ||
407 | 594 | gcc_packageset_name = u"gcc-packageset" | ||
408 | 595 | gcc_spn = self.factory.getOrMakeSourcePackageName(name="gcc") | ||
409 | 596 | apt_packageset = self.factory.makePackageset( | ||
410 | 597 | name=apt_packageset_name, distroseries=distroseries, | ||
411 | 598 | packages=(apt_spn,)) | ||
412 | 599 | gcc_packageset = self.factory.makePackageset( | ||
413 | 600 | name=gcc_packageset_name, distroseries=distroseries, | ||
414 | 601 | packages=(gcc_spn,)) | ||
415 | 602 | apt_packageset.add((gcc_packageset,)) | ||
416 | 603 | archive_name = self.getTargetArchiveName(distroseries.distribution) | ||
417 | 604 | copy_archive = self.copyArchive( | ||
418 | 605 | distroseries, archive_name, owner, | ||
419 | 606 | packageset_names=[apt_packageset_name]) | ||
420 | 607 | self.checkCopiedSources( | ||
421 | 608 | copy_archive, distroseries, package_infos[1:]) | ||
422 | 609 | |||
423 | 524 | def testCopyFromPPA(self): | 610 | def testCopyFromPPA(self): |
424 | 525 | """Test we can create a copy archive with a PPA as the source.""" | 611 | """Test we can create a copy archive with a PPA as the source.""" |
425 | 526 | ppa_owner_name = "ppa-owner" | 612 | ppa_owner_name = "ppa-owner" |
426 | @@ -712,6 +798,20 @@ | |||
427 | 712 | exception_type=SoyuzScriptError, | 798 | exception_type=SoyuzScriptError, |
428 | 713 | exception_text="Invalid user name: '%s'" % invalid_user) | 799 | exception_text="Invalid user name: '%s'" % invalid_user) |
429 | 714 | 800 | ||
430 | 801 | def testUnknownPackagesetName(self): | ||
431 | 802 | """Try copy archive population with an unknown packageset name. | ||
432 | 803 | |||
433 | 804 | The caller can request copying specific packagesets. We test | ||
434 | 805 | what happens if they request a packageset that doesn't exist. | ||
435 | 806 | """ | ||
436 | 807 | unknown_packageset = "unknown" | ||
437 | 808 | extra_args = ['-a', '386', "--package-set", unknown_packageset] | ||
438 | 809 | self.runScript( | ||
439 | 810 | extra_args=extra_args, | ||
440 | 811 | exception_type=PackageLocationError, | ||
441 | 812 | exception_text="Could not find packageset No such package set" | ||
442 | 813 | " (in the specified distro series): '%s'." % unknown_packageset) | ||
443 | 814 | |||
444 | 715 | def testPackagesetDelta(self): | 815 | def testPackagesetDelta(self): |
445 | 716 | """Try to calculate the delta between two source package sets.""" | 816 | """Try to calculate the delta between two source package sets.""" |
446 | 717 | hoary = getUtility(IDistributionSet)['ubuntu']['hoary'] | 817 | hoary = getUtility(IDistributionSet)['ubuntu']['hoary'] |
Hi James,
One minor nitpick but otherwise this branch is r=me.
> === modified file 'lib/lp/ soyuz/adapters/ packagelocation .py' soyuz/adapters/ packagelocation .py 2009-08-28 06:39:38 +0000 soyuz/adapters/ packagelocation .py 2010-06-22 12:11:56 +0000
> --- lib/lp/
> +++ lib/lp/
> @@ -63,6 +66,10 @@
> if self.component is not None:
> result += ' (%s)' % self.component.name
>
> + if self.packagesets:
We should explicitly test len() here, since we know it's going to be a
list even if it's empty.
> + result += ' [%s]' % ( s]),)
> + ", ".join([str(p.name) for p in self.packageset
> +
> return result
>
>