← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~cjwatson/launchpad/weaker-ogre-model into lp:launchpad

 

Colin Watson has proposed merging lp:~cjwatson/launchpad/weaker-ogre-model into lp:launchpad with lp:~cjwatson/launchpad/refactor-component-dependencies as a prerequisite.

Commit message:
Add DistroSeries.strict_supported_component_dependencies, which if False allows packages in supported components to build-depend on packages in unsupported components.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/weaker-ogre-model/+merge/290543

Add DistroSeries.strict_supported_component_dependencies, which if False allows packages in supported components to build-depend on packages in unsupported components.

This implements the Launchpad side of https://lists.ubuntu.com/archives/ubuntu-devel/2016-February/039188.html if enabled using a flag on DistroSeries.  publishing_options is a little misnamed for this (unfortunately I hadn't thought of this case when I added that column), but it doesn't seem worth adding another database column for this, and it'll do.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/weaker-ogre-model into lp:launchpad.
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml	2016-03-21 22:04:18 +0000
+++ lib/lp/registry/configure.zcml	2016-03-31 00:36:42 +0000
@@ -320,6 +320,7 @@
                 index_compressors
                 publish_by_hash
                 advertise_by_hash
+                strict_supported_component_dependencies
                 inherit_overrides_from_parents"/>
 
         <!-- NB: check with SABDFL before modifying these, there is potential to

=== modified file 'lib/lp/registry/interfaces/distroseries.py'
--- lib/lp/registry/interfaces/distroseries.py	2016-03-18 15:39:37 +0000
+++ lib/lp/registry/interfaces/distroseries.py	2016-03-31 00:36:42 +0000
@@ -401,6 +401,12 @@
             that apt uses them by default.  Only effective if
             publish_by_hash is also set.""")))
 
+    strict_supported_component_dependencies = exported(Bool(
+        title=_("Strict dependencies of supported components"), required=True,
+        description=_("""
+            If True, packages in supported components (main and restricted)
+            may not build-depend on packages in unsupported components.""")))
+
     inherit_overrides_from_parents = Bool(
         title=_("Inherit overrides from parents"),
         readonly=False, required=True)

=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py	2016-03-21 22:04:18 +0000
+++ lib/lp/registry/model/distroseries.py	2016-03-31 00:36:42 +0000
@@ -278,6 +278,7 @@
                     for compressor in DEFAULT_INDEX_COMPRESSORS],
                 "publish_by_hash": False,
                 "advertise_by_hash": False,
+                "strict_supported_component_dependencies": True,
                 }
         super(DistroSeries, self).__init__(*args, **kwargs)
 
@@ -861,6 +862,17 @@
         assert isinstance(value, bool)
         self.publishing_options["advertise_by_hash"] = value
 
+    @property
+    def strict_supported_component_dependencies(self):
+        return self.publishing_options.get(
+            "strict_supported_component_dependencies", True)
+
+    @strict_supported_component_dependencies.setter
+    def strict_supported_component_dependencies(self, value):
+        assert isinstance(value, bool)
+        self.publishing_options["strict_supported_component_dependencies"] = (
+            value)
+
     def _customizeSearchParams(self, search_params):
         """Customize `search_params` for this distribution series."""
         search_params.setDistroSeries(self)

=== modified file 'lib/lp/registry/stories/webservice/xx-distroseries.txt'
--- lib/lp/registry/stories/webservice/xx-distroseries.txt	2016-03-18 15:39:37 +0000
+++ lib/lp/registry/stories/webservice/xx-distroseries.txt	2016-03-31 00:36:42 +0000
@@ -89,6 +89,7 @@
     resource_type_link: ...
     self_link: u'http://.../ubuntu/hoary'
     status: u'Active Development'
+    strict_supported_component_dependencies: True
     suite_names:
         [u'Release', u'Security', u'Updates', u'Proposed', u'Backports']
     summary: u'Hoary is the ...

=== modified file 'lib/lp/registry/tests/test_distroseries.py'
--- lib/lp/registry/tests/test_distroseries.py	2016-03-18 15:39:37 +0000
+++ lib/lp/registry/tests/test_distroseries.py	2016-03-31 00:36:42 +0000
@@ -403,6 +403,17 @@
         self.assertTrue(
             naked_distroseries.publishing_options["advertise_by_hash"])
 
+    def test_strict_supported_component_dependencies(self):
+        distroseries = self.factory.makeDistroSeries()
+        self.assertTrue(distroseries.strict_supported_component_dependencies)
+        with admin_logged_in():
+            distroseries.strict_supported_component_dependencies = False
+        self.assertFalse(distroseries.strict_supported_component_dependencies)
+        naked_distroseries = removeSecurityProxy(distroseries)
+        self.assertFalse(
+            naked_distroseries.publishing_options[
+                "strict_supported_component_dependencies"])
+
 
 class TestDistroSeriesPackaging(TestCaseWithFactory):
 

=== modified file 'lib/lp/soyuz/adapters/archivedependencies.py'
--- lib/lp/soyuz/adapters/archivedependencies.py	2016-03-31 00:36:42 +0000
+++ lib/lp/soyuz/adapters/archivedependencies.py	2016-03-31 00:36:42 +0000
@@ -64,6 +64,14 @@
     'partner': ['partner'],
     }
 
+# If strict_supported_component_dependencies is disabled, treat the
+# left-hand components like the right-hand components for the purposes of
+# finding component dependencies.
+lax_component_map = {
+    'main': 'universe',
+    'restricted': 'multiverse',
+    }
+
 pocket_dependencies = {
     PackagePublishingPocket.RELEASE: (
         PackagePublishingPocket.RELEASE,
@@ -96,10 +104,11 @@
 default_component_dependency_name = 'multiverse'
 
 
-def get_components_for_context(component, pocket):
+def get_components_for_context(component, distroseries, pocket):
     """Return the components allowed to be used in the build context.
 
     :param component: the context `IComponent`.
+    :param distroseries: the context `IDistroSeries`.
     :param pocket: the context `IPocket`.
     :return: a list of component names.
     """
@@ -109,7 +118,10 @@
     if pocket == PackagePublishingPocket.BACKPORTS:
         return component_dependencies['multiverse']
 
-    return component_dependencies[component.name]
+    component_name = component.name
+    if not distroseries.strict_supported_component_dependencies:
+        component_name = lax_component_map.get(component_name, component_name)
+    return component_dependencies[component_name]
 
 
 def get_primary_current_component(archive, distroseries, sourcepackagename):
@@ -155,7 +167,8 @@
         for expanded_pocket in pocket_dependencies[pocket]:
             deps.append(
                 (archive, distro_arch_series, expanded_pocket,
-                 get_components_for_context(component, expanded_pocket)))
+                 get_components_for_context(
+                     component, distro_series, expanded_pocket)))
 
     primary_component = get_primary_current_component(
         archive, distro_series, source_package_name)
@@ -172,7 +185,8 @@
         for pocket in pocket_dependencies[archive_dependency.pocket]:
             deps.append(
                 (archive_dependency.dependency, distro_arch_series, pocket,
-                 get_components_for_context(archive_component, pocket)))
+                 get_components_for_context(
+                     archive_component, distro_series, pocket)))
 
     # Consider build tools archive dependencies.
     if tools_source is not None:
@@ -207,7 +221,8 @@
             for pocket in pocket_dependencies[dsp.pocket]:
                 deps.append(
                     (dep_archive, dep_arch_series, pocket,
-                     get_components_for_context(dsp.component, pocket)))
+                     get_components_for_context(
+                         dsp.component, dep_arch_series.distroseries, pocket)))
         except NotFoundError:
             pass
 
@@ -338,12 +353,12 @@
     return sources_list_lines
 
 
-def _get_default_primary_dependencies(archive, distro_series, component,
+def _get_default_primary_dependencies(archive, distro_arch_series, component,
                                       pocket):
     """Return the default primary dependencies for a given context.
 
     :param archive: the context `IArchive`.
-    :param distro_series: the context `IDistroSeries`.
+    :param distro_arch_series: the context `IDistroArchSeries`.
     :param component: the context `IComponent`.
     :param pocket: the context `PackagePublishingPocket`.
 
@@ -354,13 +369,14 @@
         component = getUtility(IComponentSet)[
             default_component_dependency_name]
         pocket = default_pocket_dependency
-    primary_components = get_components_for_context(component, pocket)
+    primary_components = get_components_for_context(
+        component, distro_arch_series.distroseries, pocket)
     primary_pockets = pocket_dependencies[pocket]
 
     primary_dependencies = []
     for pocket in primary_pockets:
         primary_dependencies.append(
-            (archive.distribution.main_archive, distro_series, pocket,
+            (archive.distribution.main_archive, distro_arch_series, pocket,
              primary_components))
 
     return primary_dependencies

=== modified file 'lib/lp/soyuz/doc/archive-dependencies.txt'
--- lib/lp/soyuz/doc/archive-dependencies.txt	2016-03-31 00:36:42 +0000
+++ lib/lp/soyuz/doc/archive-dependencies.txt	2016-03-31 00:36:42 +0000
@@ -75,10 +75,6 @@
     ...     get_components_for_context)
     >>> from lp.soyuz.enums import ArchivePurpose
 
-    >>> archive = factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
-    >>> ogre_build = factory.makeBinaryPackageBuild(
-    ...     archive=archive, pocket=PackagePublishingPocket.RELEASE)
-
     >>> def testOgreComponents(build):
     ...     print " Component | Ogre-Model"
     ...     print "-----------+---------------"
@@ -87,12 +83,15 @@
     ...         npub = removeSecurityProxy(build.current_source_publication)
     ...         npub.component = component
     ...         flush_database_caches()
-    ...         components_term = " ".join(
-    ...             get_components_for_context(
-    ...                 build.current_component, build.pocket))
+    ...         components_term = " ".join(get_components_for_context(
+    ...             build.current_component, build.distro_series,
+    ...             build.pocket))
     ...         print '%10s | %s' % (build.current_component.name,
     ...                              components_term)
 
+    >>> archive = factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
+    >>> ogre_build = factory.makeBinaryPackageBuild(
+    ...     archive=archive, pocket=PackagePublishingPocket.RELEASE)
     >>> testOgreComponents(ogre_build)
      Component | Ogre-Model
     -----------+---------------
@@ -102,6 +101,28 @@
     multiverse | main restricted universe multiverse
        partner | partner
 
+Series with strict_supported_component_dependencies=False additionally allow
+source packages in 'supported' components (main and restricted) to
+build-depend on binary packages in 'unsupported' components (universe and
+multiverse).
+
+    >>> lax_distroseries = factory.makeDistroSeries(
+    ...     distribution=archive.distribution)
+    >>> lax_distroseries.strict_supported_component_dependencies = False
+    >>> lax_distroarchseries = factory.makeDistroArchSeries(
+    ...     distroseries=lax_distroseries)
+    >>> lax_ogre_build = factory.makeBinaryPackageBuild(
+    ...     distroarchseries=lax_distroarchseries, archive=archive,
+    ...     pocket=PackagePublishingPocket.RELEASE)
+    >>> testOgreComponents(lax_ogre_build)
+     Component | Ogre-Model
+    -----------+---------------
+          main | main universe
+    restricted | main restricted universe multiverse
+      universe | main universe
+    multiverse | main restricted universe multiverse
+       partner | partner
+
 As fixed for bug #198936, builds for the BACKPORTS pocket are allowed
 to use any component available, independently of the component they
 are currently published. This special-case is important because it
@@ -157,7 +178,7 @@
 
     >>> for component_name in get_components_for_context(
     ...         getUtility(IComponentSet)[default_component_dependency_name],
-    ...         pocket):
+    ...         hoary, pocket):
     ...     print component_name
     main
     restricted

=== modified file 'lib/lp/soyuz/model/archivedependency.py'
--- lib/lp/soyuz/model/archivedependency.py	2016-03-31 00:36:42 +0000
+++ lib/lp/soyuz/model/archivedependency.py	2016-03-31 00:36:42 +0000
@@ -62,7 +62,13 @@
         if self.component is None:
             return pocket_title
 
-        component_part = ", ".join(
-            get_components_for_context(self.component, self.pocket))
+        # XXX cjwatson 2016-03-31: This may be inaccurate, but we can't do
+        # much better since this ArchiveDependency applies to multiple
+        # series which may each resolve component dependencies in different
+        # ways.
+        distroseries = self.archive.distribution.currentseries
+
+        component_part = ", ".join(get_components_for_context(
+            self.component, distroseries, self.pocket))
 
         return "%s (%s)" % (pocket_title, component_part)

=== modified file 'lib/lp/soyuz/scripts/initialize_distroseries.py'
--- lib/lp/soyuz/scripts/initialize_distroseries.py	2016-03-18 15:39:37 +0000
+++ lib/lp/soyuz/scripts/initialize_distroseries.py	2016-03-31 00:36:42 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2014 Canonical Ltd.  This software is licensed under the
+# Copyright 2009-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Initialize a distroseries from its parent distroseries."""
@@ -381,6 +381,9 @@
         self.distroseries.advertise_by_hash = any(
             parent.advertise_by_hash
                 for parent in self.derivation_parents)
+        self.distroseries.strict_supported_component_dependencies = any(
+            parent.strict_supported_component_dependencies
+                for parent in self.derivation_parents)
 
     def _copy_architectures(self):
         das_filter = ' AND distroseries IN %s ' % (

=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2016-03-18 15:39:37 +0000
+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2016-03-31 00:36:42 +0000
@@ -1,4 +1,4 @@
-# Copyright 2010-2015 Canonical Ltd.  This software is licensed under the
+# Copyright 2010-2016 Canonical Ltd.  This software is licensed under the
 # GNU Affero General Public License version 3 (see the file LICENSE).
 
 """Test the initialize_distroseries script machinery."""
@@ -85,6 +85,7 @@
         parent.include_long_descriptions = False
         parent.publish_by_hash = True
         parent.advertise_by_hash = True
+        parent.strict_supported_component_dependencies = False
         self._populate_parent(parent, parent_das, packages, pocket)
         return parent, parent_das
 
@@ -614,6 +615,7 @@
         self.assertFalse(child.include_long_descriptions)
         self.assertTrue(child.publish_by_hash)
         self.assertTrue(child.advertise_by_hash)
+        self.assertFalse(child.strict_supported_component_dependencies)
 
     def test_initialize(self):
         # Test a full initialize with no errors.


Follow ups