~launchpad-pqm/launchpad/devel

11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
1
# Copyright 2009 Canonical Ltd.  This software is licensed under the
2
# GNU Affero General Public License version 3 (see the file LICENSE).
3
4
"""Initialise a distroseries from its parent distroseries."""
5
6
7
__metaclass__ = type
8
__all__ = [
11258.1.6 by Steve Kowalik
* Remove unneeded import from distroseries, and move it to IDS.
9
    'InitialisationError',
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
10
    'InitialiseDistroSeries',
11
    ]
12
12771.3.4 by Steve Kowalik
Use new storm, so we can use is_empty on almost everything.
13
from operator import methodcaller
12771.3.1 by Steve Kowalik
Drop initialise_distro_series, the generic run_jobs can deal with it.
14
import transaction
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
15
from zope.component import getUtility
11403.1.4 by Henning Eggers
Reformatted imports using format-imports script r32.
16
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
17
from canonical.database.sqlbase import sqlvalues
7675.166.315 by Stuart Bishop
Be more careful about casting to Unicode
18
from canonical.launchpad.helpers import ensure_unicode
11470.1.1 by Steve Kowalik
* Switch IDS and its tests from IStoreSelector to I{Master,}Store.
19
from canonical.launchpad.interfaces.lpstorm import IMasterStore
11458.1.1 by Jelmer Vernooij
Move enums of buildmaster.
20
from lp.buildmaster.enums import BuildStatus
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
21
from lp.registry.interfaces.pocket import PackagePublishingPocket
11258.1.7 by Steve Kowalik
* Remove some more now unused imports from distroseries.
22
from lp.soyuz.adapters.packagelocation import PackageLocation
11411.6.9 by Julian Edwards
Move PackageUploadStatus and PackageUploadCustomFormat
23
from lp.soyuz.enums import (
24
    ArchivePurpose,
25
    PackageUploadStatus,
26
    )
11470.1.3 by Steve Kowalik
Run format-imports over the changed files.
27
from lp.soyuz.interfaces.archive import IArchiveSet
11584.3.3 by Steve Kowalik
* Switch to IPackageCloner, rather than clone_packages.
28
from lp.soyuz.interfaces.packagecloner import IPackageCloner
11411.7.24 by j.c.sackett
Merged from devel.
29
from lp.soyuz.interfaces.packageset import IPackagesetSet
30
from lp.soyuz.model.packageset import Packageset
11258.1.6 by Steve Kowalik
* Remove unneeded import from distroseries, and move it to IDS.
31
32
33
class InitialisationError(Exception):
34
    """Raised when there is an exception during the initialisation process."""
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
35
36
37
class InitialiseDistroSeries:
11258.1.9 by Steve Kowalik
Add a docstring to InitialiseDistroSeries, and correct slight thinko with the script's docstring
38
    """Copy in all of the parent distroseries's configuration. This
39
    includes all configuration for distroseries as well as distroarchseries,
40
    publishing and all publishing records for sources and binaries.
41
42
    Preconditions:
43
      The distroseries must exist, and be completly unused, with no source
44
      or binary packages existing, as well as no distroarchseries set up.
12494.1.86 by Gavin Panella
Set the child series' parent in InitialiseDistroSeries.
45
      Section and component selections must be empty. It must not have a
46
      parent series.
11258.1.9 by Steve Kowalik
Add a docstring to InitialiseDistroSeries, and correct slight thinko with the script's docstring
47
48
    Outcome:
49
      The distroarchseries set up in the parent series will be copied.
50
      The publishing structure will be copied from the parent. All
51
      PUBLISHED and PENDING packages in the parent will be created in
7675.1010.1 by William Grant
Excise lucilleconfig from the model.
52
      this distroseries and its distroarchseriess. All component and section
53
      selections will be duplicated, as will any permission-related
54
      structures.
11258.1.9 by Steve Kowalik
Add a docstring to InitialiseDistroSeries, and correct slight thinko with the script's docstring
55
56
    Note:
57
      This method will raise a InitialisationError when the pre-conditions
58
      are not met. After this is run, you still need to construct chroots
59
      for building, you need to add anything missing wrt. ports etc. This
60
      method is only meant to give you a basic copy of a parent series in
61
      order to assist you in preparing a new series of a distribution or
62
      in the initialisation of a derivative.
63
    """
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
64
11566.1.3 by Steve Kowalik
Merge devel, fixing conflicts
65
    def __init__(
12494.1.86 by Gavin Panella
Set the child series' parent in InitialiseDistroSeries.
66
        self, parent, distroseries, arches=(), packagesets=(), rebuild=False):
7675.883.1 by Steve Kowalik
* First shot at the deriveDistroSeries() function, and exporting it over the
67
        # Avoid circular imports
68
        from lp.registry.model.distroseries import DistroSeries
12494.1.86 by Gavin Panella
Set the child series' parent in InitialiseDistroSeries.
69
        self.parent = parent
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
70
        self.distroseries = distroseries
11393.1.1 by Steve Kowalik
* Limit the number of arches we copy when so instructed.
71
        self.arches = arches
7675.166.315 by Stuart Bishop
Be more careful about casting to Unicode
72
        self.packagesets = [
73
            ensure_unicode(packageset) for packageset in packagesets]
11584.3.1 by Steve Kowalik
Add rebuild support. Drive-by a fix to _full_initialise() in the test-suite.
74
        self.rebuild = rebuild
11470.1.1 by Steve Kowalik
* Switch IDS and its tests from IStoreSelector to I{Master,}Store.
75
        self._store = IMasterStore(DistroSeries)
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
76
11258.1.10 by Steve Kowalik
* Undo test changes.
77
    def check(self):
12494.1.86 by Gavin Panella
Set the child series' parent in InitialiseDistroSeries.
78
        if self.distroseries.parent_series is not None:
79
            raise InitialisationError(
12494.1.89 by Gavin Panella
The error message when parent_series was already set was ambiguous, misleading even.
80
                ("DistroSeries {child.name} has been initialized; it already "
81
                 "derives from {child.parent_series.distribution.name}/"
82
                 "{child.parent_series.name}.").format(
83
                    child=self.distroseries))
12828.1.2 by Steve Kowalik
Use distribution, rather than parent.
84
        if self.distroseries.distribution.id == self.parent.distribution.id:
12828.1.1 by Steve Kowalik
Don't check for pending builds if the child's distribution is not the parents.
85
            self._checkBuilds()
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
86
        self._checkQueue()
87
        self._checkSeries()
88
12771.3.2 by Steve Kowalik
Revert kwargs call to Store.find(), fix another mention of parent_series I
89
    def _checkBuilds(self):
90
        """Assert there are no pending builds for parent series.
91
92
        Only cares about the RELEASE pocket, which is the only one inherited
93
        via initialiseFromParent method.
94
        """
95
        # only the RELEASE pocket is inherited, so we only check
96
        # pending build records for it.
97
        pending_builds = self.parent.getBuildRecords(
98
            BuildStatus.NEEDSBUILD, pocket=PackagePublishingPocket.RELEASE)
99
100
        if pending_builds.any():
101
            raise InitialisationError("Parent series has pending builds.")
102
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
103
    def _checkQueue(self):
104
        """Assert upload queue is empty on parent series.
105
106
        Only cares about the RELEASE pocket, which is the only one inherited
107
        via initialiseFromParent method.
108
        """
109
        # only the RELEASE pocket is inherited, so we only check
110
        # queue items for it.
111
        for queue in (
112
            PackageUploadStatus.NEW, PackageUploadStatus.ACCEPTED,
113
            PackageUploadStatus.UNAPPROVED):
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
114
            items = self.parent.getQueueItems(
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
115
                queue, pocket=PackagePublishingPocket.RELEASE)
116
            if items:
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
117
                raise InitialisationError(
11258.1.6 by Steve Kowalik
* Remove unneeded import from distroseries, and move it to IDS.
118
                    "Parent series queues are not empty.")
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
119
120
    def _checkSeries(self):
11258.1.6 by Steve Kowalik
* Remove unneeded import from distroseries, and move it to IDS.
121
        error = (
122
            "Can not copy distroarchseries from parent, there are "
123
            "already distroarchseries(s) initialised for this series.")
12771.3.1 by Steve Kowalik
Drop initialise_distro_series, the generic run_jobs can deal with it.
124
        sources = self.distroseries.getAllPublishedSources()
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
125
        binaries = self.distroseries.getAllPublishedBinaries()
12771.3.4 by Steve Kowalik
Use new storm, so we can use is_empty on almost everything.
126
        if not all(
127
            map(methodcaller('is_empty'), (
128
                sources, binaries, self.distroseries.architectures,
129
                self.distroseries.sections))):
130
            raise InitialisationError(error)
131
        if self.distroseries.components:
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
132
            raise InitialisationError(error)
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
133
134
    def initialise(self):
12771.3.3 by Steve Kowalik
Move set_parent back.
135
        self._set_parent()
7675.1082.4 by William Grant
Fix initial-distroseries to copy it.
136
        self._copy_configuration()
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
137
        self._copy_architectures()
138
        self._copy_packages()
11316.8.2 by Steve Kowalik
* Allow lucille to INSERT into packageset
139
        self._copy_packagesets()
12771.3.1 by Steve Kowalik
Drop initialise_distro_series, the generic run_jobs can deal with it.
140
        transaction.commit()
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
141
12494.1.86 by Gavin Panella
Set the child series' parent in InitialiseDistroSeries.
142
    def _set_parent(self):
143
        self.distroseries.parent_series = self.parent
144
7675.1082.4 by William Grant
Fix initial-distroseries to copy it.
145
    def _copy_configuration(self):
146
        self.distroseries.backports_not_automatic = \
147
            self.parent.backports_not_automatic
148
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
149
    def _copy_architectures(self):
11393.1.1 by Steve Kowalik
* Limit the number of arches we copy when so instructed.
150
        include = ''
151
        if self.arches:
152
            include = "AND architecturetag IN %s" % sqlvalues(self.arches)
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
153
        self._store.execute("""
154
            INSERT INTO DistroArchSeries
11643.2.4 by Steve Kowalik
Revert earlier change to .createMissingBuilds(), and create the builds in the
155
            (distroseries, processorfamily, architecturetag, owner, official)
156
            SELECT %s, processorfamily, architecturetag, %s, official
7675.838.1 by Steve Kowalik
Don't copy disabled DASes in InitialiseDistroSeries. Add a test that doesn't
157
            FROM DistroArchSeries WHERE distroseries = %s
158
            AND enabled = TRUE %s
11393.1.1 by Steve Kowalik
* Limit the number of arches we copy when so instructed.
159
            """ % (sqlvalues(self.distroseries, self.distroseries.owner,
160
            self.parent) + (include,)))
12771.3.1 by Steve Kowalik
Drop initialise_distro_series, the generic run_jobs can deal with it.
161
        self._store.flush()
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
162
        self.distroseries.nominatedarchindep = self.distroseries[
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
163
            self.parent.nominatedarchindep.architecturetag]
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
164
165
    def _copy_packages(self):
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
166
        # Perform the copies
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
167
        self._copy_component_section_and_format_selections()
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
168
169
        # Prepare the list of distroarchseries for which binary packages
170
        # shall be copied.
171
        distroarchseries_list = []
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
172
        for arch in self.distroseries.architectures:
11393.1.1 by Steve Kowalik
* Limit the number of arches we copy when so instructed.
173
            if self.arches and (arch.architecturetag not in self.arches):
174
                continue
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
175
            parent_arch = self.parent[arch.architecturetag]
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
176
            distroarchseries_list.append((parent_arch, arch))
177
        # Now copy source and binary packages.
178
        self._copy_publishing_records(distroarchseries_list)
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
179
        self._copy_packaging_links()
180
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
181
    def _copy_publishing_records(self, distroarchseries_list):
182
        """Copy the publishing records from the parent arch series
183
        to the given arch series in ourselves.
184
185
        We copy all PENDING and PUBLISHED records as PENDING into our own
186
        publishing records.
187
11258.1.4 by Steve Kowalik
Correct docstring, and copy debug archives too
188
        We copy only the RELEASE pocket in the PRIMARY and DEBUG archives.
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
189
        """
190
        archive_set = getUtility(IArchiveSet)
191
11566.1.2 by Steve Kowalik
First step to limit spns in the package cloner
192
        spns = []
11566.1.9 by Steve Kowalik
* Rename spns to sourcepackagenames in the packagecloner.
193
        # The overhead from looking up each packageset is mitigated by
12771.3.1 by Steve Kowalik
Drop initialise_distro_series, the generic run_jobs can deal with it.
194
        # this usually running from a job.
11566.1.2 by Steve Kowalik
First step to limit spns in the package cloner
195
        if self.packagesets:
196
            for pkgsetname in self.packagesets:
11566.1.7 by Steve Kowalik
* Merge from ids-no-more sampledata.
197
                pkgset = getUtility(IPackagesetSet).getByName(
198
                    pkgsetname, distroseries=self.parent)
11566.1.4 by Steve Kowalik
Second step to limit spns in the package cloner
199
                spns += list(pkgset.getSourcesIncluded())
11566.1.2 by Steve Kowalik
First step to limit spns in the package cloner
200
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
201
        for archive in self.parent.distribution.all_distro_archives:
11258.1.7 by Steve Kowalik
* Remove some more now unused imports from distroseries.
202
            if archive.purpose not in (
11258.1.4 by Steve Kowalik
Correct docstring, and copy debug archives too
203
                ArchivePurpose.PRIMARY, ArchivePurpose.DEBUG):
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
204
                continue
205
206
            target_archive = archive_set.getByDistroPurpose(
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
207
                self.distroseries.distribution, archive.purpose)
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
208
            if archive.purpose is ArchivePurpose.PRIMARY:
209
                assert target_archive is not None, (
210
                    "Target archive doesn't exist?")
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
211
            origin = PackageLocation(
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
212
                archive, self.parent.distribution, self.parent,
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
213
                PackagePublishingPocket.RELEASE)
214
            destination = PackageLocation(
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
215
                target_archive, self.distroseries.distribution,
216
                self.distroseries, PackagePublishingPocket.RELEASE)
12771.3.2 by Steve Kowalik
Revert kwargs call to Store.find(), fix another mention of parent_series I
217
            proc_families = None
11584.3.2 by Steve Kowalik
Drop 'is True' when checking if rebuild is set
218
            if self.rebuild:
12771.3.2 by Steve Kowalik
Revert kwargs call to Store.find(), fix another mention of parent_series I
219
                proc_families = [
220
                    das[1].processorfamily
221
                    for das in distroarchseries_list]
11584.3.1 by Steve Kowalik
Add rebuild support. Drive-by a fix to _full_initialise() in the test-suite.
222
                distroarchseries_list = ()
11584.3.3 by Steve Kowalik
* Switch to IPackageCloner, rather than clone_packages.
223
            getUtility(IPackageCloner).clonePackages(
224
                origin, destination, distroarchseries_list,
11566.1.7 by Steve Kowalik
* Merge from ids-no-more sampledata.
225
                proc_families, spns, self.rebuild)
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
226
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
227
    def _copy_component_section_and_format_selections(self):
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
228
        """Copy the section, component and format selections from the parent
229
        distro series into this one.
230
        """
231
        # Copy the component selections
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
232
        self._store.execute('''
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
233
            INSERT INTO ComponentSelection (distroseries, component)
234
            SELECT %s AS distroseries, cs.component AS component
235
            FROM ComponentSelection AS cs WHERE cs.distroseries = %s
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
236
            ''' % sqlvalues(self.distroseries.id,
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
237
            self.parent.id))
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
238
        # Copy the section selections
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
239
        self._store.execute('''
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
240
            INSERT INTO SectionSelection (distroseries, section)
241
            SELECT %s as distroseries, ss.section AS section
242
            FROM SectionSelection AS ss WHERE ss.distroseries = %s
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
243
            ''' % sqlvalues(self.distroseries.id,
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
244
            self.parent.id))
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
245
        # Copy the source format selections
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
246
        self._store.execute('''
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
247
            INSERT INTO SourcePackageFormatSelection (distroseries, format)
248
            SELECT %s as distroseries, spfs.format AS format
249
            FROM SourcePackageFormatSelection AS spfs
250
            WHERE spfs.distroseries = %s
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
251
            ''' % sqlvalues(self.distroseries.id,
11258.1.8 by Steve Kowalik
* Fix the 3 tests that use .initialiseFromParent() to use
252
            self.parent.id))
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
253
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
254
    def _copy_packaging_links(self):
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
255
        """Copy the packaging links from the parent series to this one."""
11258.1.3 by Steve Kowalik
* Clean up the test to reflect that the script will now error and then exit,
256
        self._store.execute("""
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
257
            INSERT INTO
258
                Packaging(
259
                    distroseries, sourcepackagename, productseries,
260
                    packaging, owner)
261
            SELECT
262
                ChildSeries.id,
263
                Packaging.sourcepackagename,
264
                Packaging.productseries,
265
                Packaging.packaging,
266
                Packaging.owner
267
            FROM
268
                Packaging
269
                -- Joining the parent distroseries permits the query to build
270
                -- the data set for the series being updated, yet results are
271
                -- in fact the data from the original series.
272
                JOIN Distroseries ChildSeries
12771.3.7 by Steve Kowalik
Revert the _copy_packaging_links changes
273
                    ON Packaging.distroseries = ChildSeries.parent_series
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
274
            WHERE
275
                -- Select only the packaging links that are in the parent
276
                -- that are not in the child.
277
                ChildSeries.id = %s
278
                AND Packaging.sourcepackagename in (
279
                    SELECT sourcepackagename
280
                    FROM Packaging
281
                    WHERE distroseries in (
282
                        SELECT id
283
                        FROM Distroseries
12771.3.7 by Steve Kowalik
Revert the _copy_packaging_links changes
284
                        WHERE id = ChildSeries.parent_series
11258.1.1 by Steve Kowalik
First shot of moving IDistroSeries.initialiseFromParent out into it's own
285
                        )
286
                    EXCEPT
287
                    SELECT sourcepackagename
288
                    FROM Packaging
289
                    WHERE distroseries in (
290
                        SELECT id
291
                        FROM Distroseries
292
                        WHERE id = ChildSeries.id
293
                        )
294
                    )
12771.3.7 by Steve Kowalik
Revert the _copy_packaging_links changes
295
            """ % self.distroseries.id)
11316.8.2 by Steve Kowalik
* Allow lucille to INSERT into packageset
296
297
    def _copy_packagesets(self):
298
        """Copy packagesets from the parent distroseries."""
11411.7.24 by j.c.sackett
Merged from devel.
299
        packagesets = self._store.find(Packageset, distroseries=self.parent)
300
        parent_to_child = {}
301
        # Create the packagesets, and any archivepermissions
302
        for parent_ps in packagesets:
12685.4.1 by William Grant
Preserve packageset ownership when initialising a new series of a distribution. It's set to the new distro owner when initialising a new distro.
303
            # Cross-distro initialisations get packagesets owned by the
304
            # distro owner, otherwise the old owner is preserved.
11566.1.1 by Steve Kowalik
Add limited support for copying only specified packagesets
305
            if self.packagesets and parent_ps.name not in self.packagesets:
306
                continue
12685.4.1 by William Grant
Preserve packageset ownership when initialising a new series of a distribution. It's set to the new distro owner when initialising a new distro.
307
            if self.distroseries.distribution == self.parent.distribution:
308
                new_owner = parent_ps.owner
309
            else:
12685.4.2 by William Grant
Use the distroseries owner instead, like it was initially.
310
                new_owner = self.distroseries.owner
11411.7.24 by j.c.sackett
Merged from devel.
311
            child_ps = getUtility(IPackagesetSet).new(
312
                parent_ps.name, parent_ps.description,
12685.4.1 by William Grant
Preserve packageset ownership when initialising a new series of a distribution. It's set to the new distro owner when initialising a new distro.
313
                new_owner, distroseries=self.distroseries,
11411.7.24 by j.c.sackett
Merged from devel.
314
                related_set=parent_ps)
315
            self._store.execute("""
316
                INSERT INTO Archivepermission
317
                (person, permission, archive, packageset, explicit)
318
                SELECT person, permission, %s, %s, explicit
319
                FROM Archivepermission WHERE packageset = %s
320
                """ % sqlvalues(
321
                    self.distroseries.main_archive, child_ps.id,
322
                    parent_ps.id))
323
            parent_to_child[parent_ps] = child_ps
324
        # Copy the relations between sets, and the contents
325
        for old_series_ps, new_series_ps in parent_to_child.items():
326
            old_series_sets = old_series_ps.setsIncluded(
327
                direct_inclusion=True)
328
            for old_series_child in old_series_sets:
329
                new_series_ps.add(parent_to_child[old_series_child])
330
            new_series_ps.add(old_series_ps.sourcesIncluded(
331
                direct_inclusion=True))