Merge lp:~cjohnston/launchpad/dd-initialization into lp:launchpad

Proposed by Chris Johnston
Status: Merged
Merged at revision: 17121
Proposed branch: lp:~cjohnston/launchpad/dd-initialization
Merge into: lp:launchpad
Diff against target: 353 lines (+152/-22)
6 files modified
lib/canonical/launchpad/icing/style.css (+5/-0)
lib/lp/registry/javascript/distroseries/initseries.js (+43/-6)
lib/lp/registry/javascript/distroseries/tests/test_initseries.js (+19/-1)
lib/lp/soyuz/model/initializedistroseriesjob.py (+8/-5)
lib/lp/soyuz/scripts/initialize_distroseries.py (+12/-8)
lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py (+65/-2)
To merge this branch: bzr merge lp:~cjohnston/launchpad/dd-initialization
Reviewer Review Type Date Requested Status
William Grant code Approve
Review via email: mp+226796@code.launchpad.net

Commit message

Allow a user to copy all, some or no packages when initializing a new distro series.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

The packageset_import widget isn't exactly choosing which packagesets to import; not every package is in a packageset, so choosing to copy ("import" isn't a term that Launchpad ever uses for copying packages internally) all packages does more than copy all the packagesets. I'd say it's the widget that chooses which packages to copy.

Consider "Don't copy any packages", "Copy all packages", "Copy some packagesets". It probably also makes sense to only show the packageset selection widget in the "some" case.

Revision history for this message
William Grant (wgrant) :
Revision history for this message
William Grant (wgrant) :
review: Needs Fixing (code)
Revision history for this message
William Grant (wgrant) :
review: Needs Fixing (code)
Revision history for this message
William Grant (wgrant) wrote :

For tests, packagesets=None seems like a more sensible default than packagesets=[]. Would it make more sense to change the tests that need [] to use [] explicitly?

Revision history for this message
William Grant (wgrant) :
review: Needs Fixing (code)
Revision history for this message
William Grant (wgrant) :
Revision history for this message
William Grant (wgrant) :
review: Needs Fixing (code)
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=== modified file 'lib/canonical/launchpad/icing/style.css'
2--- lib/canonical/launchpad/icing/style.css 2014-05-29 07:27:25 +0000
3+++ lib/canonical/launchpad/icing/style.css 2014-07-22 20:32:02 +0000
4@@ -876,6 +876,11 @@
5 display: none;
6 }
7
8+/* Hide the packageset picker widget on the Initialize series page */
9+.yui3-packagesetpickerwidget-hidden {
10+ display: none;
11+}
12+
13 /* Search results*/
14
15 #search-results {
16
17=== modified file 'lib/lp/registry/javascript/distroseries/initseries.js'
18--- lib/lp/registry/javascript/distroseries/initseries.js 2012-07-07 14:00:30 +0000
19+++ lib/lp/registry/javascript/distroseries/initseries.js 2014-07-22 20:32:02 +0000
20@@ -47,6 +47,8 @@
21 this.registerWidget(this.architectureChoice);
22 this.architectureIndepChoice = config.architectureIndepChoice;
23 this.registerWidget(this.architectureIndepChoice);
24+ this.packageCopyChoice = config.packageCopyChoice;
25+ this.registerWidget(this.packageCopyChoice);
26 this.packagesetChoice = config.packagesetChoice;
27 this.registerWidget(this.packagesetChoice);
28 this.packageCopyOptions = config.packageCopyOptions;
29@@ -139,6 +141,16 @@
30 var values = attrselect("value");
31 var arch_indep = values(
32 this.architectureIndepChoice.get("choice"))[0];
33+ var copy_package = this.packageCopyChoice !== null ?
34+ this.packageCopyChoice.get("choice").value : 'all';
35+ var packageset_ids = [];
36+ if (copy_package === 'none') {
37+ packageset_ids = [];
38+ } else if (copy_package === 'all') {
39+ packageset_ids = null;
40+ } else {
41+ packageset_ids = values(this.packagesetChoice.get("choice"));
42+ }
43 var config = {
44 on: {
45 start: function() {
46@@ -160,8 +172,7 @@
47 archindep_archtag:
48 arch_indep === this.architectureIndepChoice.AUTOSELECT ?
49 null : arch_indep,
50- packagesets: this.packagesetChoice !== null ?
51- values(this.packagesetChoice.get("choice")) : [],
52+ packagesets: packageset_ids,
53 rebuild:
54 this.packageCopyOptions.get("choice").value === "rebuild",
55 overlays: this.deriveFromChoices.get("overlays"),
56@@ -267,8 +278,22 @@
57 "Choose the architecture tag that should be " +
58 "used to build architecture independent binaries.")
59 .render(form_table_body);
60+ var package_copy_choice = null;
61 var packageset_choice = null;
62 if (cache.is_first_derivation) {
63+ package_copy_choice =
64+ new formwidgets.ChoiceListWidget()
65+ .set("name", "field.package_copy_choice")
66+ .set("multiple", false)
67+ .set("label", "Packages to copy:")
68+ .set("description",
69+ "Choose which packages to copy from the parent series ")
70+ .set("choices", [
71+ {text: "Copy all packages", value: "all"},
72+ {text: "Copy some packagesets", value: "some"},
73+ {text: "Don't copy any packages", value: "none"}])
74+ .set("choice", "all")
75+ .render(form_table_body);
76 packageset_choice =
77 new widgets.PackagesetPickerWidget()
78 .set("name", "field.packagesets")
79@@ -278,10 +303,7 @@
80 .set("multiple", true)
81 .set("label", "Package sets to copy from parent:")
82 .set("description",
83- "The package sets that will be imported " +
84- "into the derived distroseries (select none " +
85- "if you want to import all the available " +
86- "package sets).")
87+ "Select the package sets to copy.")
88 .render(form_table_body);
89 }
90 var package_copy_options =
91@@ -304,6 +326,7 @@
92 deriveFromChoices: parents_selection,
93 architectureChoice: architecture_choice,
94 architectureIndepChoice: arch_indep_choice,
95+ packageCopyChoice: package_copy_choice,
96 packagesetChoice: packageset_choice,
97 packageCopyOptions: package_copy_options,
98 form_container: form_container
99@@ -363,6 +386,20 @@
100 form_actions.architectureChoice.remove_distroseries(parent_id);
101 form_actions.packagesetChoice.remove_distroseries(parent_id);
102 });
103+
104+ // Hide packagesetChoice by default
105+ form_actions.packagesetChoice.hide();
106+
107+ // Unhide packagesetChoice if user wants to specify which packagesets
108+ // to copy.
109+ form_actions.packageCopyChoice.on('change', function (e) {
110+ var val = e.currentTarget.get('choice').value;
111+ if (val === 'some') {
112+ form_actions.packagesetChoice.show();
113+ } else {
114+ form_actions.packagesetChoice.hide();
115+ }
116+ });
117 }
118 else {
119 // Disable rebuilding if cache.is_first_derivation is false.
120
121=== modified file 'lib/lp/registry/javascript/distroseries/tests/test_initseries.js'
122--- lib/lp/registry/javascript/distroseries/tests/test_initseries.js 2012-10-26 10:00:20 +0000
123+++ lib/lp/registry/javascript/distroseries/tests/test_initseries.js 2014-07-22 20:32:02 +0000
124@@ -69,6 +69,15 @@
125 return {value: "sparc", text: "sparc"};
126 }
127 },
128+ packageCopyChoice: {
129+ get: function(name) {
130+ Assert.areEqual("choice", name);
131+ return {
132+ value: "some",
133+ text: "Copy some packagesets"
134+ };
135+ }
136+ },
137 packagesetChoice: {
138 get: function(name) {
139 Assert.areEqual("choice", name);
140@@ -266,6 +275,14 @@
141 form_actions.deriveFromChoices.get("parents"));
142 },
143
144+ testDefaultCopyChoice: function() {
145+ var cache = {is_first_derivation: true};
146+ var form_actions = initseries.setupWidgets(cache);
147+ Assert.areEqual(
148+ "all",
149+ form_actions.packageCopyChoice.get('choice').value);
150+ },
151+
152 testDefaultRebuildChoice: function() {
153 var cache = {is_first_derivation: true};
154 var form_actions = initseries.setupWidgets(cache);
155@@ -328,7 +345,8 @@
156 ArrayAssert.itemsAreEqual(
157 ['4', '5'],
158 form_actions.deriveFromChoices.get("parents"));
159- // No packageset choice widget.
160+ // No packageCopyChoice widget or packageset choice widget.
161+ Assert.isNull(form_actions.packageCopyChoice);
162 Assert.isNull(form_actions.packagesetChoice);
163 // The architecture picker features the architectures
164 // from the previous series.
165
166=== modified file 'lib/lp/soyuz/model/initializedistroseriesjob.py'
167--- lib/lp/soyuz/model/initializedistroseriesjob.py 2014-05-28 12:23:10 +0000
168+++ lib/lp/soyuz/model/initializedistroseriesjob.py 2014-07-22 20:32:02 +0000
169@@ -51,7 +51,7 @@
170
171 @classmethod
172 def create(cls, child, parents, arches=(), archindep_archtag=None,
173- packagesets=(), rebuild=False, overlays=(),
174+ packagesets=None, rebuild=False, overlays=(),
175 overlay_pockets=(), overlay_components=()):
176 """Create a new `InitializeDistroSeriesJob`.
177
178@@ -139,9 +139,12 @@
179 self.overlay_pockets[i],
180 self.overlay_components[i]))
181 parts += ",".join(parents)
182- pkgsets = [
183- IStore(Packageset).get(Packageset, int(pkgsetid)).name
184- for pkgsetid in self.packagesets]
185+ if self.packagesets is None:
186+ pkgsets = None
187+ else:
188+ pkgsets = [
189+ IStore(Packageset).get(Packageset, int(pkgsetid)).name
190+ for pkgsetid in self.packagesets]
191 parts += ", architectures: %s" % (self.arches,)
192 parts += ", archindep_archtag: %s" % self.archindep_archtag
193 parts += ", packagesets: %s" % pkgsets
194@@ -187,7 +190,7 @@
195 @property
196 def packagesets(self):
197 if self.metadata['packagesets'] is None:
198- return ()
199+ return None
200 else:
201 return tuple(self.metadata['packagesets'])
202
203
204=== modified file 'lib/lp/soyuz/scripts/initialize_distroseries.py'
205--- lib/lp/soyuz/scripts/initialize_distroseries.py 2014-07-04 11:21:54 +0000
206+++ lib/lp/soyuz/scripts/initialize_distroseries.py 2014-07-22 20:32:02 +0000
207@@ -102,7 +102,7 @@
208
209 def __init__(
210 self, distroseries, parents=(), arches=(), archindep_archtag=None,
211- packagesets=(), rebuild=False, overlays=(), overlay_pockets=(),
212+ packagesets=None, rebuild=False, overlays=(), overlay_pockets=(),
213 overlay_components=()):
214 self.distroseries = distroseries
215 self.parent_ids = [int(id) for id in parents]
216@@ -114,10 +114,14 @@
217 key=lambda parent: self.parent_ids.index(parent.id))
218 self.arches = arches
219 self.archindep_archtag = archindep_archtag
220- self.packagesets_ids = [
221- ensure_unicode(packageset) for packageset in packagesets]
222- self.packagesets = bulk.load(
223- Packageset, [int(packageset) for packageset in packagesets])
224+ if packagesets is None:
225+ self.packagesets_ids = None
226+ self.packagesets = None
227+ else:
228+ self.packagesets_ids = [
229+ ensure_unicode(packageset) for packageset in packagesets]
230+ self.packagesets = bulk.load(
231+ Packageset, [int(packageset) for packageset in packagesets])
232 self.rebuild = rebuild
233 self.overlays = overlays
234 self.overlay_pockets = overlay_pockets
235@@ -326,7 +330,7 @@
236 def _create_dsds(self):
237 if not self.first_derivation:
238 if (self._has_same_parents_as_previous_series() and
239- not self.packagesets_ids):
240+ self.packagesets_ids is None):
241 # If the parents are the same as previous_series's
242 # parents and all the packagesets are being copied,
243 # then we simply copy the DSDs from previous_series
244@@ -483,7 +487,7 @@
245 parent so the list of packages to consider in not empty.
246 """
247 source_names_by_parent = {}
248- if self.packagesets_ids:
249+ if self.packagesets_ids is not None:
250 for parent in self.derivation_parents:
251 spns = []
252 for pkgset in self.packagesets:
253@@ -663,7 +667,7 @@
254 for parent_ps in packagesets:
255 # Cross-distro initializations get packagesets owned by the
256 # distro owner, otherwise the old owner is preserved.
257- if (self.packagesets_ids and
258+ if (self.packagesets_ids is not None and
259 str(parent_ps.id) not in self.packagesets_ids):
260 continue
261 packageset_set = getUtility(IPackagesetSet)
262
263=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
264--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py 2014-07-16 00:57:21 +0000
265+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py 2014-07-22 20:32:02 +0000
266@@ -89,7 +89,7 @@
267 pocket=PackagePublishingPocket.RELEASE):
268 if packages is None:
269 packages = {'udev': '0.1-1', 'libc6': '2.8-1',
270- 'postgresql': '9.0-1', 'chromium': '3.6'}
271+ 'postgresql': '9.0-1', 'chromium': '3.6', 'vim': '7.4'}
272 for package in packages.keys():
273 spn = self.factory.getOrMakeSourcePackageName(package)
274 spph = self.factory.makeSourcePackagePublishingHistory(
275@@ -115,7 +115,7 @@
276 self.factory.makeBinaryPackageFile(binarypackagerelease=bpr)
277
278 def _fullInitialize(self, parents, child=None, previous_series=None,
279- arches=(), archindep_archtag=None, packagesets=(),
280+ arches=(), archindep_archtag=None, packagesets=None,
281 rebuild=False, distribution=None, overlays=(),
282 overlay_pockets=(), overlay_components=()):
283 if child is None:
284@@ -847,6 +847,69 @@
285 self.assertEqual(child.sourcecount, len(packages))
286 self.assertEqual(child.binarycount, 2) # Chromium is FTBFS
287
288+ def test_copy_limit_packagesets_empty(self):
289+ # If a parent series has packagesets, we don't want to copy any of them
290+ self.parent, self.parent_das = self.setupParent()
291+ test1 = getUtility(IPackagesetSet).new(
292+ u'test1', u'test 1 packageset', self.parent.owner,
293+ distroseries=self.parent)
294+ getUtility(IPackagesetSet).new(
295+ u'test2', u'test 2 packageset', self.parent.owner,
296+ distroseries=self.parent)
297+ packages = ('udev', 'chromium', 'libc6')
298+ for pkg in packages:
299+ test1.addSources(pkg)
300+ packageset1 = getUtility(IPackagesetSet).getByName(
301+ self.parent, u'test1')
302+ child = self._fullInitialize(
303+ [self.parent], packagesets=[])
304+ self.assertRaises(
305+ NoSuchPackageSet, getUtility(IPackagesetSet).getByName,
306+ child, u'test1')
307+ self.assertRaises(
308+ NoSuchPackageSet, getUtility(IPackagesetSet).getByName,
309+ child, u'test2')
310+ self.assertEqual(child.sourcecount, 0)
311+ self.assertEqual(child.binarycount, 0)
312+
313+ def test_copy_limit_packagesets_none(self):
314+ # If a parent series has packagesets, we want to copy all of them
315+ self.parent, self.parent_das = self.setupParent()
316+ test1 = getUtility(IPackagesetSet).new(
317+ u'test1', u'test 1 packageset', self.parent.owner,
318+ distroseries=self.parent)
319+ test2 = getUtility(IPackagesetSet).new(
320+ u'test2', u'test 2 packageset', self.parent.owner,
321+ distroseries=self.parent)
322+ packages_test1 = ('udev', 'chromium', 'libc6')
323+ packages_test2 = ('postgresql', 'vim')
324+ for pkg in packages_test1:
325+ test1.addSources(pkg)
326+ for pkg in packages_test2:
327+ test2.addSources(pkg)
328+ packageset1 = getUtility(IPackagesetSet).getByName(
329+ self.parent, u'test1')
330+ packageset2 = getUtility(IPackagesetSet).getByName(
331+ self.parent, u'test2')
332+ child = self._fullInitialize(
333+ [self.parent], packagesets=None)
334+ child_test1 = getUtility(IPackagesetSet).getByName(child, u'test1')
335+ child_test2 = getUtility(IPackagesetSet).getByName(child, u'test2')
336+ self.assertEqual(test1.description, child_test1.description)
337+ self.assertEqual(test2.description, child_test2.description)
338+ parent_srcs_test1 = test1.getSourcesIncluded(direct_inclusion=True)
339+ child_srcs_test1 = child_test1.getSourcesIncluded(
340+ direct_inclusion=True)
341+ self.assertEqual(parent_srcs_test1, child_srcs_test1)
342+ parent_srcs_test2 = test2.getSourcesIncluded(direct_inclusion=True)
343+ child_srcs_test2 = child_test2.getSourcesIncluded(
344+ direct_inclusion=True)
345+ self.assertEqual(parent_srcs_test2, child_srcs_test2)
346+ child.updatePackageCount()
347+ self.assertEqual(child.sourcecount,
348+ len(packages_test1) + len(packages_test2))
349+ self.assertEqual(child.binarycount, 4) # Chromium is FTBFS
350+
351 def test_rebuild_flag(self):
352 # No binaries will get copied if we specify rebuild=True.
353 self.parent, self.parent_das = self.setupParent()