← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~rvb/launchpad/bug-869221 into lp:launchpad

 

Raphaël Victor Badin has proposed merging lp:~rvb/launchpad/bug-869221 into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #869221 in Launchpad itself: "Initializing a distroseries that doesn't use the parent's archindep arch will fail"
  https://bugs.launchpad.net/launchpad/+bug/869221

For more details, see:
https://code.launchpad.net/~rvb/launchpad/bug-869221/+merge/78548

Before that branch, the arch independent builder for the derived series was simply taken from the first parent, no question asked. This is obviously a problem if the architecture in question was not among the architectures selected for the derived series.

This branch fixes that:
- In the case of multiple parents, we try to find a candidate for the child's nominatedarch.arch_tag by computing the intersection between the list of the parents architecture indep builders and the selected architectures;
- If this list is empty a proper error is raised.

A following branch will force the user to include a proper architecture in the list of the selected archtectures on the +initseries.

= Tests =

./bin/test -vvc test_initialize_distroseries test_multiple_parents_child_nominatedarchindep
./bin/test -vvc test_initialize_distroseries test_multiple_parents_no_child_nominatedarchindep

= QA =

*Test 1*
Initialize a series with architectures 'a' and 'b' ('b' being the arch indep one).  Only select architecture 'a' for the child.  The init job should error with the proper error message: "The distroseries has no architectures selected to build architecture independent binaries."

*Test 2*
Initialize a series from 2 parents: p1 and p2, p1 having two archtectures 'a' and 'b' ('b' being the arch indep one) and p2 having one architecture 'a' ('a' being - obviously - the arch indep one).  Then initialize a child with only architecture 'a'.  This should succeed and the nominatedarchindep for the resulting child should be 'a'.
-- 
https://code.launchpad.net/~rvb/launchpad/bug-869221/+merge/78548
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~rvb/launchpad/bug-869221 into lp:launchpad.
=== modified file 'lib/lp/soyuz/scripts/initialize_distroseries.py'
--- lib/lp/soyuz/scripts/initialize_distroseries.py	2011-10-03 09:28:45 +0000
+++ lib/lp/soyuz/scripts/initialize_distroseries.py	2011-10-07 08:20:30 +0000
@@ -157,11 +157,22 @@
                  ".").format(
                     child=self.distroseries))
         self._checkParents()
+        self._checkArchindep()
         for parent in self.derivation_parents:
             self._checkBuilds(parent)
             self._checkQueue(parent)
         self._checkSeries()
 
+    def _checkArchindep(self):
+        # Check that the child distroseries has an architecture to
+        # build architecture independent binaries.
+        potential_nominated_arches = self._potential_nominated_arches(
+             self.derivation_parents)
+        if (len(potential_nominated_arches) == 0):
+            raise InitializationError(
+                ("The distroseries has no architectures selected to "
+                 "build architecture independent binaries."))
+
     def _checkPublisherConfig(self):
         """A series cannot be initialized if it has no publisher config
         set up.
@@ -365,9 +376,23 @@
             """ % (sqlvalues(self.distroseries, self.distroseries.owner)
             + (das_filter, )))
         self._store.flush()
-        # Take nominatedarchindep from the first parent.
-        self.distroseries.nominatedarchindep = self.distroseries[
-            self.derivation_parents[0].nominatedarchindep.architecturetag]
+        # Select the arch-indep builder from the intersection between
+        # the selected architectures and the list of the parent's
+        # arch-indep builders.
+        arch_tag = self._potential_nominated_arches(
+            self.derivation_parents).pop()
+        self.distroseries.nominatedarchindep = self.distroseries[arch_tag]
+
+    def _potential_nominated_arches(self, parent_list):
+        parent_indep_archtags = set(
+            parent.nominatedarchindep.architecturetag
+            for parent in parent_list
+            if parent.nominatedarchindep is not None)
+
+        if len(self.arches) == 0:
+            return parent_indep_archtags
+        else:
+            return parent_indep_archtags.intersection(self.arches)
 
     def _copy_packages(self):
         # Perform the copies

=== modified file 'lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py'
--- lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2011-10-03 09:28:45 +0000
+++ lib/lp/soyuz/scripts/tests/test_initialize_distroseries.py	2011-10-07 08:20:30 +0000
@@ -259,7 +259,7 @@
         parent, parent_das, parent_das2, source = res
         # Create builds for the architecture of parent_das2.
         source.createMissingBuilds(architectures_available=[parent_das2])
-        # Initialize only with parent_das2's architecture.
+        # Initialize only with parent_das's architecture.
         child = self.factory.makeDistroSeries()
         ids = InitializeDistroSeries(
             child, [parent.id], arches=[parent_das2.architecturetag])
@@ -293,13 +293,13 @@
         # architecture we're initializing with, IDS will succeed.
         res = self.create2archParentAndSource(packages={'p1': '1.1'})
         parent, parent_das, parent_das2, source = res
-        # Create builds for the architecture of parent_das2.
-        source.createMissingBuilds(architectures_available=[parent_das2])
-        # Initialize only with parent_das's architecture.
+        # Create builds for the architecture of parent_das.
+        source.createMissingBuilds(architectures_available=[parent_das])
+        # Initialize only with parent_das2's architecture.
         child = self.factory.makeDistroSeries(
             distribution=parent.distribution, previous_series=parent)
         ids = InitializeDistroSeries(
-            child, arches=[parent_das.architecturetag])
+            child, arches=[parent_das2.architecturetag])
 
         # No error is raised because we're initializing only the architecture
         # which has no pending builds in it.
@@ -1383,3 +1383,39 @@
         self.assertEqual([], self.getWaitingJobs(child, 'p2', prev_parent2))
         self.assertNotEqual([], self.getWaitingJobs(child, 'p1', parent3))
         self.assertEqual([], self.getWaitingJobs(child, 'p3', parent3))
+
+    def test_multiple_parents_child_nominatedarchindep(self):
+        # If the list of the selected architectures and the list of the
+        # nominatedarchindep for all the parent intersect, the child's
+        # nominatedarchindep is taken from the intersection of the two
+        # lists.
+        parent1, unused = self.setupParent(
+            packages={}, arch_tag='i386')
+        parent2, unused = self.setupParent(
+            packages={}, arch_tag='amd64')
+        child = self._fullInitialize(
+            [parent1, parent2],
+            arches=[parent2.nominatedarchindep.architecturetag])
+        self.assertEqual(
+            child.nominatedarchindep.architecturetag,
+            parent2.nominatedarchindep.architecturetag)
+
+    def test_multiple_parents_no_child_nominatedarchindep(self):
+        # If the list of the selected architectures and the list of the
+        # nominatedarchindep for all the parents don't intersect, an
+        # error is raised because it means that the child won't have an
+        # architecture to build architecture independent binaries.
+        parent1, unused = self.setupParent(
+            packages={}, arch_tag='i386')
+        self.setupDas(parent1, 'hppa', 'powerpc')
+        parent2, unused = self.setupParent(
+            packages={}, arch_tag='amd64')
+        child = self.factory.makeDistroSeries()
+        ids = InitializeDistroSeries(
+            child, [parent1.id, parent2.id],
+            arches=['powerpc'])
+        self.assertRaisesWithContent(
+            InitializationError,
+            ("The distroseries has no architectures selected to "
+             "build architecture independent binaries."),
+            ids.check)