~launchpad-pqm/launchpad/devel

« back to all changes in this revision

Viewing changes to lib/lp/soyuz/scripts/initialize_distroseries.py

[r=gmb][bug=789091] Add support to be able to initialize a series in
        a distribution with already initialized series.

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
    includes all configuration for distroseries as well as distroarchseries,
52
52
    publishing and all publishing records for sources and binaries.
53
53
 
 
54
    We support 2 use cases here:
 
55
      #1 If the child distribution has zero initialized series:
 
56
        - the parent list can't be empty (otherwise we trigger an error);
 
57
        - the series will be derived from the parents passed as argument;
 
58
        - the parents will be set to the parents passed as argument;
 
59
        - first_derivation = True.
 
60
      #2 If the child distribution has more than zero initialized series:
 
61
        - the series will be derived from the previous_series;
 
62
        - the parents will be set to the parents passed as argument or
 
63
          the parents of the previous_series if the passed argument is empty;
 
64
        - first_derivation = False.
 
65
 
54
66
    Preconditions:
55
67
      The distroseries must exist, and be completly unused, with no source
56
68
      or binary packages existing, as well as no distroarchseries set up.
75
87
    """
76
88
 
77
89
    def __init__(
78
 
        self, distroseries, parents, arches=(), packagesets=(),
 
90
        self, distroseries, parents=(), arches=(), packagesets=(),
79
91
        rebuild=False, overlays=(), overlay_pockets=(),
80
92
        overlay_components=()):
81
93
        # Avoid circular imports
98
110
        self.overlay_components = overlay_components
99
111
        self._store = IMasterStore(DistroSeries)
100
112
 
 
113
        self.first_derivation = (
 
114
            not self.distroseries.distribution.has_published_sources)
 
115
        if self.first_derivation:
 
116
            # Use-case #1.
 
117
            self.derivation_parents = self.parents
 
118
            self.derivation_parent_ids = self.parent_ids
 
119
        else:
 
120
            # Use-case #2.
 
121
            self.derivation_parents = [self.distroseries.previous_series]
 
122
            self.derivation_parent_ids = [
 
123
                p.id for p in self.derivation_parents]
 
124
            if self.parent_ids == []:
 
125
                self.parents = (
 
126
                    self.distroseries.previous_series.getParentSeries())
 
127
 
101
128
    def check(self):
102
129
        if self.distroseries.isDerivedSeries():
103
130
            raise InitializationError(
104
131
                ("DistroSeries {child.name} has already been initialized"
105
132
                 ".").format(
106
133
                    child=self.distroseries))
107
 
        for parent in self.parents:
 
134
        self._checkParents()
 
135
        for parent in self.derivation_parents:
108
136
            if self.distroseries.distribution.id == parent.distribution.id:
109
137
                self._checkBuilds(parent)
110
138
            self._checkQueue(parent)
111
139
        self._checkSeries()
112
140
 
 
141
    def _checkParents(self):
 
142
        """If self.first_derivation, the parents list cannot be empty."""
 
143
        if self.first_derivation:
 
144
            # Use-case #1.
 
145
            if len(self.parent_ids) == 0:
 
146
                raise InitializationError(
 
147
                    ("Distroseries {child.name} cannot be initialized: "
 
148
                     "No other series in the distribution is initialized "
 
149
                     "and no parent was passed to the initilization method"
 
150
                     ".").format(
 
151
                        child=self.distroseries))
 
152
 
113
153
    def _checkBuilds(self, parent):
114
154
        """Assert there are no pending builds for the given parent series.
115
155
 
195
235
 
196
236
    def _copy_configuration(self):
197
237
        self.distroseries.backports_not_automatic = any(
198
 
            parent.backports_not_automatic for parent in self.parents)
 
238
            parent.backports_not_automatic
 
239
                for parent in self.derivation_parents)
199
240
 
200
241
    def _copy_architectures(self):
201
242
        das_filter = ' AND distroseries IN %s ' % (
202
 
                sqlvalues(self.parent_ids))
 
243
                sqlvalues([p.id for p in self.derivation_parents]))
203
244
        if self.arches:
204
245
            das_filter += ' AND architecturetag IN %s ' % (
205
246
                sqlvalues(self.arches))
215
256
        self._store.flush()
216
257
        # Take nominatedarchindep from the first parent.
217
258
        self.distroseries.nominatedarchindep = self.distroseries[
218
 
            self.parents[0].nominatedarchindep.architecturetag]
 
259
            self.derivation_parents[0].nominatedarchindep.architecturetag]
219
260
 
220
261
    def _copy_packages(self):
221
262
        # Perform the copies
224
265
        # Prepare the lists of distroarchseries for which binary packages
225
266
        # shall be copied.
226
267
        distroarchseries_lists = {}
227
 
        for parent in self.parents:
 
268
        for parent in self.derivation_parents:
228
269
            distroarchseries_lists[parent] = []
229
270
            for arch in self.distroseries.architectures:
230
271
                if self.arches and (arch.architecturetag not in self.arches):
282
323
                pkgset = self._store.get(Packageset, int(pkgsetid))
283
324
                spns += list(pkgset.getSourcesIncluded())
284
325
 
285
 
        for parent in self.parents:
 
326
        for parent in self.derivation_parents:
286
327
            distroarchseries_list = distroarchseries_lists[parent]
287
328
            for archive in parent.distribution.all_distro_archives:
288
329
                if archive.purpose not in (
344
385
            SELECT DISTINCT %s AS distroseries, cs.component AS component
345
386
            FROM ComponentSelection AS cs WHERE cs.distroseries IN %s
346
387
            ''' % sqlvalues(self.distroseries.id,
347
 
            self.parent_ids))
 
388
            self.derivation_parent_ids))
348
389
        # Copy the section selections
349
390
        self._store.execute('''
350
391
            INSERT INTO SectionSelection (distroseries, section)
351
392
            SELECT DISTINCT %s as distroseries, ss.section AS section
352
393
            FROM SectionSelection AS ss WHERE ss.distroseries IN %s
353
394
            ''' % sqlvalues(self.distroseries.id,
354
 
            self.parent_ids))
 
395
            self.derivation_parent_ids))
355
396
        # Copy the source format selections
356
397
        self._store.execute('''
357
398
            INSERT INTO SourcePackageFormatSelection (distroseries, format)
359
400
            FROM SourcePackageFormatSelection AS spfs
360
401
            WHERE spfs.distroseries IN %s
361
402
            ''' % sqlvalues(self.distroseries.id,
362
 
            self.parent_ids))
 
403
            self.derivation_parent_ids))
363
404
 
364
405
    def _copy_packaging_links(self):
365
406
        """Copy the packaging links from the parent series to this one."""
366
407
        # We iterate over the parents and copy into the child in
367
408
        # sequence to avoid creating duplicates.
368
 
        for parent_id in self.parent_ids:
 
409
        for parent_id in self.derivation_parent_ids:
369
410
            self._store.execute("""
370
411
                INSERT INTO
371
412
                    Packaging(
414
455
        from lp.registry.model.distroseries import DistroSeries
415
456
 
416
457
        packagesets = self._store.find(
417
 
            Packageset, DistroSeries.id.is_in(self.parent_ids))
 
458
            Packageset, DistroSeries.id.is_in(self.derivation_parent_ids))
418
459
        parent_to_child = {}
419
460
        # Create the packagesets, and any archivepermissions
420
461
        parent_distro_ids = [
421
 
            parent.distribution.id for parent in self.parents]
 
462
            parent.distribution.id for parent in self.derivation_parents]
422
463
        for parent_ps in packagesets:
423
464
            # Cross-distro initializations get packagesets owned by the
424
465
            # distro owner, otherwise the old owner is preserved.