pmb.parse.apkindex: account for provider_priority when locating packages

This fixes an issue where the local apk index has two packages in it
that provide the same thing, but this function was returning only the
one with the shortest name... which could be very bad :)

https://gitlab.postmarketos.org/postmarketOS/pmaports/-/merge_requests/6475#note_480167

In the process, add tests for pmb.parse.apkindex.package function. Some of
the tests would fail without this patch, surfacing a bug where priorities
are not considered, but should, and that we are now fixing.

Co-authored-by: Clayton Craft <craftyguy@postmarketos.org>
Part-of: https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/merge_requests/2594
This commit is contained in:
Pablo Correa Gómez 2025-05-11 15:59:23 +02:00 committed by Stefan Hansson
parent 71f01ddbeb
commit ba6bb4272d
No known key found for this signature in database
GPG key ID: ACD854892B38D898
2 changed files with 122 additions and 1 deletions

View file

@ -483,6 +483,16 @@ def package(
if package in package_providers:
return package_providers[package]
if package_providers:
providers_priority = provider_highest_priority(package_providers, package)
num_providers = len(providers_priority)
# Only one provider with max priority: return it
if num_providers == 1:
return next(iter(providers_priority.values()))
# Multiple providers with max priority: let follow-on logic decide
elif num_providers > 1:
package_providers = providers_priority
# Any provider
if package_providers:
return pmb.parse.apkindex.provider_shortest(package_providers, package)

View file

@ -7,7 +7,11 @@ import pytest
import pmb.parse.apkindex
from pmb.parse.apkindex import parse as parse_apkindex, clear_cache as clear_apkindex_cache
from pmb.parse.apkindex import (
parse as parse_apkindex,
clear_cache as clear_apkindex_cache,
package as package_apkindex,
)
example_apkindex = """
C:Q1p+nGf5oBAmbU9FQvV4MhfEmWqVE=
@ -443,3 +447,110 @@ def test_apkindex_parse_cache_hit(valid_apkindex_file, monkeypatch) -> None:
with pytest.raises(AssertionError):
parse_apkindex(valid_apkindex_file)
def test_apkindex_package(valid_apkindex_file) -> None:
index_block = package_apkindex(
"postmarketos-base-ui-networkmanager", arch=Arch.aarch64, indexes=[valid_apkindex_file]
)
assert index_block.pkgname == "postmarketos-base-ui-networkmanager"
index_block = package_apkindex(
"postmarketos-base-ui-wifi", arch=Arch.aarch64, indexes=[valid_apkindex_file]
)
assert index_block.pkgname == "postmarketos-base-ui-wifi-wpa_supplicant"
def test_apkindex_package_provider_priority(tmp_path) -> None:
tmpfile = tmp_path / "APKINDEX.5"
f = open(tmpfile, "w")
# A snippet of the above example but with a missing timestamp
# and origin fields
f.write(
"""
C:Q1yB3CVUFMOjnLOOEAUIUUpJJV8g0=
P:postmarketos-base-short
V:20-r0
A:aarch64
S:1587
I:22
T:openrc config for postmarketOS
U:https://postmarketos.org
L:GPL-3.0-or-later
o:postmarketos-base
m:Clayton Craft <clayton@craftyguy.net>
t:1729538699
c:901cb9520450a1e88ded95ac774e83f6b2cfbba3-dirty
D:!systemd alpine-conf busybox-mdev-openrc busybox-openrc openrc
p:postmarketos-base-init
k:10
C:Q1yB3CVUFMOjnLOOEAUIUUpJJV8g0=
P:postmarketos-base-loooooooooong
V:22-r0
A:aarch64
S:1587
I:22
T:systemd base config for postmarketOS
U:https://postmarketos.org
L:GPL-3.0-or-later
o:postmarketos-base-systemd
m:Clayton Craft <clayton@craftyguy.net>
t:1729538699
c:901cb9520450a1e88ded95ac774e83f6b2cfbba3-dirty
D:kbd kmod less login-utils systemd systemd-services systemd-timesyncd tzdata
p:postmarketos-base-init
k:100
"""
)
f.close()
index_block = package_apkindex("postmarketos-base-init", arch=Arch.aarch64, indexes=[tmpfile])
assert index_block.pkgname == "postmarketos-base-loooooooooong"
assert index_block.origin == "postmarketos-base-systemd"
assert index_block.provides == ["postmarketos-base-init"]
def test_apkindex_package_provider_shortest(tmp_path) -> None:
tmpfile = tmp_path / "APKINDEX.6"
f = open(tmpfile, "w")
# A snippet of the above example but with a missing timestamp
# and origin fields
f.write(
"""
C:Q1yB3CVUFMOjnLOOEAUIUUpJJV8g0=
P:mesa-egl
V:20-r0
A:aarch64
S:1587
I:22
T:mesa package
U:https://postmarketos.org
L:GPL-3.0-or-later
o:mesa
m:Clayton Craft <clayton@craftyguy.net>
t:1729538699
c:901cb9520450a1e88ded95ac774e83f6b2cfbba3-dirty
p:so:libGL.so.1=20-r0
C:Q1yB3CVUFMOjnLOOEAUIUUpJJV8g0=
P:mesa-purism-gc7000-egl
V:22-r0
A:aarch64
S:1587
I:22
T:mesa fork for Purism
U:https://postmarketos.org
L:GPL-3.0-or-later
o:mesa-purism-gc7000
m:Clayton Craft <clayton@craftyguy.net>
t:1729538699
c:901cb9520450a1e88ded95ac774e83f6b2cfbba3-dirty
p:so:libGL.so.1=22-r0
"""
)
f.close()
index_block = package_apkindex("so:libGL.so.1", arch=Arch.aarch64, indexes=[tmpfile])
assert index_block.pkgname == "mesa-egl"
assert index_block.origin == "mesa"