forked from Mirror/pmbootstrap
pmb.parse.apkindex: Introduce proper typing (MR 2425)
And adjust other code. Closes https://gitlab.postmarketos.org/postmarketOS/pmbootstrap/-/issues/2455
This commit is contained in:
parent
566b43edd4
commit
71772b9b6b
18 changed files with 279 additions and 179 deletions
|
@ -9,10 +9,9 @@ See also:
|
|||
- pmb/helpers/repo.py (work with binary package repos)
|
||||
"""
|
||||
|
||||
import copy
|
||||
from typing import Any, overload
|
||||
from typing import overload
|
||||
from pmb.core.arch import Arch
|
||||
from pmb.core.context import get_context
|
||||
from pmb.core.package_metadata import PackageMetadata
|
||||
from pmb.helpers import logging
|
||||
import pmb.build._package
|
||||
|
||||
|
@ -30,27 +29,33 @@ def remove_operators(package):
|
|||
|
||||
|
||||
@overload
|
||||
def get(pkgname: str, arch: Arch, replace_subpkgnames: bool = False) -> dict[str, Any]: ...
|
||||
def get(pkgname: str, arch: Arch, replace_subpkgnames: bool = ...) -> PackageMetadata: ...
|
||||
|
||||
|
||||
@overload
|
||||
def get(
|
||||
pkgname: str, arch: Arch, replace_subpkgnames: bool = False, must_exist: bool = True
|
||||
) -> dict[str, Any] | None: ...
|
||||
pkgname: str, arch: Arch, replace_subpkgnames: bool = ..., must_exist: bool = ...
|
||||
) -> PackageMetadata | None: ...
|
||||
|
||||
|
||||
@overload
|
||||
def get(
|
||||
pkgname: str,
|
||||
arch: Arch,
|
||||
replace_subpkgnames: bool = False,
|
||||
must_exist: bool = True,
|
||||
try_other_arches: bool = True,
|
||||
) -> dict[str, Any] | None: ...
|
||||
replace_subpkgnames: bool = ...,
|
||||
must_exist: bool = ...,
|
||||
try_other_arches: bool = ...,
|
||||
) -> PackageMetadata | None: ...
|
||||
|
||||
|
||||
@Cache("pkgname", "arch", "replace_subpkgnames", "try_other_arches")
|
||||
def get(pkgname, arch, replace_subpkgnames=False, must_exist=True, try_other_arches=True):
|
||||
def get(
|
||||
pkgname: str,
|
||||
arch: Arch,
|
||||
replace_subpkgnames: bool = False,
|
||||
must_exist: bool = True,
|
||||
try_other_arches: bool = True,
|
||||
) -> PackageMetadata | None:
|
||||
"""Find a package in pmaports, and as fallback in the APKINDEXes of the binary packages.
|
||||
|
||||
:param pkgname: package name (e.g. "hello-world")
|
||||
|
@ -71,50 +76,37 @@ def get(pkgname, arch, replace_subpkgnames=False, must_exist=True, try_other_arc
|
|||
* None if the package was not found
|
||||
"""
|
||||
# Find in pmaports
|
||||
ret: dict[str, Any] = {}
|
||||
ret: PackageMetadata | None = None
|
||||
pmaport = pmb.helpers.pmaports.get(pkgname, False)
|
||||
if pmaport:
|
||||
ret = {
|
||||
"arch": pmaport["arch"],
|
||||
"depends": pmb.build._package.get_depends(get_context(), pmaport),
|
||||
"pkgname": pmaport["pkgname"],
|
||||
"provides": pmaport["provides"],
|
||||
"version": pmaport["pkgver"] + "-r" + pmaport["pkgrel"],
|
||||
}
|
||||
ret = PackageMetadata.from_pmaport(pmaport)
|
||||
|
||||
# Find in APKINDEX (given arch)
|
||||
if not ret or not pmb.helpers.pmaports.check_arches(ret["arch"], arch):
|
||||
if not ret or not pmb.helpers.pmaports.check_arches(ret.arch, arch):
|
||||
pmb.helpers.repo.update(arch)
|
||||
ret_repo = pmb.parse.apkindex.package(pkgname, arch, False)
|
||||
|
||||
# Save as result if there was no pmaport, or if the pmaport can not be
|
||||
# built for the given arch, but there is a binary package for that arch
|
||||
# (e.g. temp/mesa can't be built for x86_64, but Alpine has it)
|
||||
if not ret or (ret_repo and ret_repo["arch"] == arch):
|
||||
ret = ret_repo
|
||||
if ret_repo and (not ret or ret_repo.arch == arch):
|
||||
ret = PackageMetadata.from_apkindex_block(ret_repo)
|
||||
|
||||
# Find in APKINDEX (other arches)
|
||||
if not ret and try_other_arches:
|
||||
pmb.helpers.repo.update()
|
||||
for arch_i in Arch.supported():
|
||||
if arch_i != arch:
|
||||
ret = pmb.parse.apkindex.package(pkgname, arch_i, False)
|
||||
apkindex_block = pmb.parse.apkindex.package(pkgname, arch_i, False)
|
||||
if apkindex_block is not None:
|
||||
ret = PackageMetadata.from_apkindex_block(apkindex_block)
|
||||
if ret:
|
||||
break
|
||||
|
||||
# Copy ret (it might have references to caches of the APKINDEX or APKBUILDs
|
||||
# and we don't want to modify those!)
|
||||
if ret:
|
||||
ret = copy.deepcopy(ret)
|
||||
|
||||
# Make sure ret["arch"] is a list (APKINDEX code puts a string there)
|
||||
if ret and isinstance(ret["arch"], str):
|
||||
ret["arch"] = [ret["arch"]]
|
||||
|
||||
# Replace subpkgnames if desired
|
||||
if replace_subpkgnames:
|
||||
if replace_subpkgnames and ret:
|
||||
depends_new = []
|
||||
for depend in ret["depends"]:
|
||||
for depend in ret.depends:
|
||||
depend_data = get(depend, arch, must_exist=False, try_other_arches=try_other_arches)
|
||||
if not depend_data:
|
||||
logging.warning(f"WARNING: {pkgname}: failed to resolve" f" dependency '{depend}'")
|
||||
|
@ -122,10 +114,10 @@ def get(pkgname, arch, replace_subpkgnames=False, must_exist=True, try_other_arc
|
|||
if depend not in depends_new:
|
||||
depends_new += [depend]
|
||||
continue
|
||||
depend_pkgname = depend_data["pkgname"]
|
||||
depend_pkgname = depend_data.pkgname
|
||||
if depend_pkgname not in depends_new:
|
||||
depends_new += [depend_pkgname]
|
||||
ret["depends"] = depends_new
|
||||
ret.depends = depends_new
|
||||
|
||||
# Save to cache and return
|
||||
if ret:
|
||||
|
@ -141,7 +133,7 @@ def get(pkgname, arch, replace_subpkgnames=False, must_exist=True, try_other_arc
|
|||
|
||||
|
||||
@Cache("pkgname", "arch")
|
||||
def depends_recurse(pkgname, arch):
|
||||
def depends_recurse(pkgname: str, arch: Arch) -> list[str]:
|
||||
"""Recursively resolve all of the package's dependencies.
|
||||
|
||||
:param pkgname: name of the package (e.g. "device-samsung-i9100")
|
||||
|
@ -158,19 +150,19 @@ def depends_recurse(pkgname, arch):
|
|||
package = get(pkgname_queue, arch)
|
||||
|
||||
# Add its depends to the queue
|
||||
for depend in package["depends"]:
|
||||
for depend in package.depends:
|
||||
if depend not in ret:
|
||||
queue += [depend]
|
||||
|
||||
# Add the pkgname (not possible subpkgname) to ret
|
||||
if package["pkgname"] not in ret:
|
||||
ret += [package["pkgname"]]
|
||||
if package.pkgname not in ret:
|
||||
ret += [package.pkgname]
|
||||
ret.sort()
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def check_arch(pkgname, arch, binary=True):
|
||||
def check_arch(pkgname: str, arch: Arch, binary: bool = True) -> bool:
|
||||
"""Check if a package be built for a certain architecture, or is there a binary package for it.
|
||||
|
||||
:param pkgname: name of the package
|
||||
|
@ -181,7 +173,7 @@ def check_arch(pkgname, arch, binary=True):
|
|||
:returns: True when the package can be built, or there is a binary package, False otherwise
|
||||
"""
|
||||
if binary:
|
||||
arches = get(pkgname, arch)["arch"]
|
||||
arches = get(pkgname, arch).arch
|
||||
else:
|
||||
arches = pmb.helpers.pmaports.get(pkgname, must_exist=True)["arch"]
|
||||
return pmb.helpers.pmaports.check_arches(arches, arch)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue