diff --git a/pmb/parse/apkindex.py b/pmb/parse/apkindex.py index e07539b1..395a8424 100644 --- a/pmb/parse/apkindex.py +++ b/pmb/parse/apkindex.py @@ -42,6 +42,7 @@ def parse_next_block(args, path, lines, start): "o": "origin", "P": "pkgname", "p": "provides", + "k": "provider_priority", "t": "timestamp", "V": "version", } @@ -321,6 +322,32 @@ def providers(args, package, arch=None, must_exist=True, indexes=None): return ret +def provider_highest_priority(providers, pkgname): + """ + Get the provider(s) with the highest provider_priority and log a message. + + :param providers: returned dict from providers(), must not be empty + :param pkgname: the package name we are interested in (for the log message) + """ + max_priority = 0 + priority_providers = collections.OrderedDict() + for provider_name, provider in providers.items(): + priority = int(provider.get("provider_priority", -1)) + if priority > max_priority: + priority_providers.clear() + max_priority = priority + if priority == max_priority: + priority_providers[provider_name] = provider + + if priority_providers: + logging.debug(f"{pkgname}: picked provider(s) with higest priority {max_priority}: " + + ", ".join(priority_providers.keys())) + return priority_providers + + # None of the providers seems to have a provider_priority defined + return providers + + def provider_shortest(providers, pkgname): """ Get the provider with the shortest pkgname and log a message. In most cases diff --git a/pmb/parse/depends.py b/pmb/parse/depends.py index 032ae1f4..1a48a80b 100644 --- a/pmb/parse/depends.py +++ b/pmb/parse/depends.py @@ -73,7 +73,12 @@ def package_provider(args, pkgname, pkgnames_install, suffix="native"): " the '" + suffix + "' chroot already") return provider - # 5. Pick the provider + # 5. Pick the provider(s) with the highest priority + providers = pmb.parse.apkindex.provider_highest_priority(providers, pkgname) + if len(providers) == 1: + return list(providers.values())[0] + + # 6. Pick the shortest provider. (Note: Normally apk would fail here!) return pmb.parse.apkindex.provider_shortest(providers, pkgname) diff --git a/test/test_parse_apkindex.py b/test/test_parse_apkindex.py index 1ae3c574..886980ac 100644 --- a/test/test_parse_apkindex.py +++ b/test/test_parse_apkindex.py @@ -300,6 +300,43 @@ def test_providers_highest_version(args, monkeypatch): assert providers["test"]["version"] == "3" +def test_provider_highest_priority(args, monkeypatch): + # Verify that it picks the provider with highest priority + func = pmb.parse.apkindex.provider_highest_priority + + provider_none_a = {"pkgname": "a", "provides": ["test"]} + provider_none_b = {"pkgname": "b", "provides": ["test"]} + provider_low_c = {"pkgname": "c", "provides": ["test"], + "provider_priority": 42} + provider_low_d = {"pkgname": "d", "provides": ["test"], + "provider_priority": 42} + provider_high = {"pkgname": "e", "provides": ["test"], + "provider_priority": 1337} + + # No provider has a priority + providers = {"a": provider_none_a} + assert func(providers, "test") == providers + providers = {"a": provider_none_a, "b": provider_none_b} + assert func(providers, "test") == providers + + # One provider has a priority, another one does not + providers = {"a": provider_none_a, "e": provider_high} + assert func(providers, "test") == {"e": provider_high} + + # One provider has a priority, another one has a higher priority + providers = {"c": provider_low_c, "e": provider_high} + assert func(providers, "test") == {"e": provider_high} + + # One provider has a priority, another one has the same priority + providers = {"c": provider_low_c, "d": provider_low_d} + assert func(providers, "test") == providers + + # + some package without priority at all should be filtered out + providers2 = providers.copy() + providers2["a"] = provider_none_a + assert func(providers2, "test") == providers + + def test_package(args, monkeypatch): # Override pmb.parse.apkindex.providers() providers = collections.OrderedDict() diff --git a/test/test_parse_depends.py b/test/test_parse_depends.py index 28b630f6..866f5632 100644 --- a/test/test_parse_depends.py +++ b/test/test_parse_depends.py @@ -72,7 +72,14 @@ def test_package_provider(args, monkeypatch): pkgnames_install = [] assert func(args, pkgname, pkgnames_install) == package - # 5. Pick the first one + # 5. Pick package with highest priority + package_with_priority = {"pkgname": "test-priority", "provides": ["test"], + "provider_priority": 100} + providers = {"test-two": package_two, "test-priority": package_with_priority} + assert func(args, pkgname, pkgnames_install) == package_with_priority + + # 6. Pick the first one + providers = {"test_": package, "test-two": package_two} installed = {} assert func(args, pkgname, pkgnames_install) == package