From d1f6631f3bbe4f7a6ab2d8440b4477270614b7f8 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Mar 27 2019 05:36:43 +0000 Subject: Fix traceback in MMDResolver when transitive dependency cannot be satisfied. This fixes problems from #1184 when new platform stream is added and the input module depends on another module which is not built against this new platform, but in the same time the input module wants to be built against this new platform stream. See the unit-test for more info. The problem is that `MMDResolver.solve()` method sets the `alternative` to an empty list and stores the data there only if the alternative is found valid. If the alternative is not found valid, then it stays set to an empty list, but the code using `alternative` later expects it to only contains valid alternatives. This commit fixes this by setting the `alternative` only in a case we found it is valid alternative. --- diff --git a/module_build_service/mmd_resolver.py b/module_build_service/mmd_resolver.py index 574a03e..0b0ae52 100644 --- a/module_build_service/mmd_resolver.py +++ b/module_build_service/mmd_resolver.py @@ -510,9 +510,8 @@ class MMDResolver(object): kfunc = s2nsvc elif policy == MMDResolverPolicy.First: kfunc = s2ns + # `key` contains tuple similar to "('gtk:1', 'foo:1')" key = tuple(kfunc(s) for s in opt) - # `key` now contains tuple similar to "('gtk:1', 'foo:1')" - alternative = src_alternatives.setdefault(key, []) # Create the solving jobs. # We need to say to libsolv that we want it to prefer modules from the combination @@ -559,6 +558,7 @@ class MMDResolver(object): # Remember that src_alternatives are grouped by NS or NSVC depending on # MMDResolverPolicy, so there might be more of them. if all_solvables_found: + alternative = src_alternatives.setdefault(key, []) alternative.append(newsolvables) else: log.debug(" - ^ Not all favored solvables found in the result, skipping.") diff --git a/tests/test_mmd_resolver.py b/tests/test_mmd_resolver.py index 7a9f6c8..fd08a0e 100644 --- a/tests/test_mmd_resolver.py +++ b/tests/test_mmd_resolver.py @@ -326,3 +326,30 @@ class TestMMDResolver: with pytest.raises(RuntimeError, match=err_msg_regex): self.mmd_resolver.solve(app) + + def test_solve_new_platform(self,): + """ + Tests that MMDResolver works in case we add new platform and there is + modular dependency of input module which is built only against old + platforms and in the same time the input module wants to be built + with all available platforms. + """ + modules = ( + ("platform:f28:0:c0", {}), + ("platform:f29:0:c0", {}), + ("platform:f30:0:c0", {}), + ("gtk:3:0:c8", {"platform": ["f28"]}), + ("gtk:3:0:c9", {"platform": ["f29"]}), + ) + for n, req in modules: + self.mmd_resolver.add_modules(self._make_mmd(n, req)) + + app = self._make_mmd("app:1:0", {"platform": [], "gtk": ["3"]}) + expanded = self.mmd_resolver.solve(app) + + # Build only against f28 and f29, because "gtk:3" is not built against f30. + expected = set([ + frozenset(['gtk:3:0:c8:x86_64', 'app:1:0:0:src', 'platform:f28:0:c0:x86_64']), + frozenset(['gtk:3:0:c9:x86_64', 'app:1:0:0:src', 'platform:f29:0:c0:x86_64'])]) + + assert expanded == expected