Replace skip_extra_repos -> with_extra_repos (MR 2480)

Replace the boolean skip_extra_repos with a new with_extra_repos
argument that can be default, enabled or disabled.

This will be used to explicitly enable extra repos in a package search
even if systemd is currently disabled, so we can display a hint when a
package was not found because systemd is disabled in a follow-up patch.
This commit is contained in:
Oliver Smith 2024-11-07 18:04:06 +01:00
parent 444d9e256f
commit 0a0f6ead33
No known key found for this signature in database
GPG key ID: 5AE7F5513E0885CB
6 changed files with 51 additions and 28 deletions

View file

@ -11,13 +11,13 @@ from pmb.meta import Cache
def is_systemd_selected(config: Config) -> bool:
if "systemd" not in pmb.config.pmaports.read_config_repos():
return False
if pmb.helpers.ui.check_option(config.ui, "pmb:systemd-never", skip_extra_repos=True):
if pmb.helpers.ui.check_option(config.ui, "pmb:systemd-never", with_extra_repos="disabled"):
return False
if config.systemd == SystemdConfig.ALWAYS:
return True
if config.systemd == SystemdConfig.NEVER:
return False
return pmb.helpers.ui.check_option(config.ui, "pmb:systemd", skip_extra_repos=True)
return pmb.helpers.ui.check_option(config.ui, "pmb:systemd", with_extra_repos="disabled")
def systemd_selected_str(config: Config) -> tuple[str, str]:

View file

@ -6,22 +6,30 @@ from collections.abc import Generator
import pmb.config
from pmb.core.context import get_context
from pmb.meta import Cache
from pmb.types import WithExtraRepos
@Cache(skip_extras=False)
def pkgrepo_paths(skip_extras: bool = False) -> list[Path]:
@Cache("with_extra_repos")
def pkgrepo_paths(with_extra_repos: WithExtraRepos = "default") -> list[Path]:
config = get_context().config
paths = list(map(lambda x: Path(x), config.aports))
if not paths:
raise RuntimeError("No package repositories specified?")
if skip_extras:
with_systemd = False
match with_extra_repos:
case "disabled":
return paths
case "enabled":
with_systemd = True
case "default":
with_systemd = pmb.config.is_systemd_selected(config)
out_paths = []
for p in paths:
# This isn't very generic, but we don't plan to add new extra-repos...
if (p / "extra-repos/systemd").is_dir() and pmb.config.is_systemd_selected(config):
if (p / "extra-repos/systemd").is_dir() and with_systemd:
out_paths.append(p / "extra-repos/systemd")
out_paths.append(p)
@ -30,16 +38,16 @@ def pkgrepo_paths(skip_extras: bool = False) -> list[Path]:
@Cache()
def pkgrepo_default_path() -> Path:
return pkgrepo_paths(skip_extras=True)[0]
return pkgrepo_paths(with_extra_repos="disabled")[0]
def pkgrepo_names(skip_exras: bool = False) -> list[str]:
def pkgrepo_names(with_extra_repos: WithExtraRepos = "default") -> list[str]:
"""
Return a list of all the package repository names. We REQUIRE
that the last repository is "pmaports", though the directory
may be named differently. So we hardcode the name here.
"""
names = [aports.name for aports in pkgrepo_paths(skip_exras)]
names = [aports.name for aports in pkgrepo_paths(with_extra_repos)]
names[-1] = "pmaports"
return names
@ -112,14 +120,16 @@ def pkgrepo_iglob(path: str, recursive: bool = False) -> Generator[Path, None, N
yield pdir
def pkgrepo_iter_package_dirs(skip_extra_repos: bool = False) -> Generator[Path, None, None]:
def pkgrepo_iter_package_dirs(
with_extra_repos: WithExtraRepos = "default",
) -> Generator[Path, None, None]:
"""
Yield each matching glob over each aports repository.
Detect duplicates within the same aports repository but otherwise
ignore all but the first. This allows for overriding packages.
"""
seen: dict[str, list[str]] = dict(map(lambda a: (a, []), pkgrepo_names(skip_extra_repos)))
for repo in pkgrepo_paths(skip_extra_repos):
seen: dict[str, list[str]] = dict(map(lambda a: (a, []), pkgrepo_names(with_extra_repos)))
for repo in pkgrepo_paths(with_extra_repos):
for g in glob.iglob(os.path.join(repo, "**/*/APKBUILD"), recursive=True):
pdir = Path(g).parent
# Skip extra-repos when not parsing the extra-repo itself

View file

@ -19,6 +19,7 @@ def test_pkgrepo_pmaports(pmaports, monkeypatch):
# Disable results caching
pkgrepo_paths.cache_disable()
pkgrepo_default_path.cache_disable()
paths = pkgrepo_paths()
print(f"[master] pkgrepo_paths: {paths}")
@ -37,7 +38,10 @@ def test_pkgrepo_pmaports(pmaports, monkeypatch):
== 0
)
paths = pkgrepo_paths()
paths = pkgrepo_paths(with_extra_repos="disabled")
assert len(paths) == 1
paths = pkgrepo_paths(with_extra_repos="enabled")
assert len(paths) == 2
# systemd is the first path, since we want packages there to take priority

View file

@ -13,15 +13,16 @@ from pmb.core.pkgrepo import pkgrepo_iter_package_dirs
from pmb.helpers import logging
from pathlib import Path
from typing import Any
from pmb.types import WithExtraRepos
from pmb.meta import Cache
import pmb.parse
@Cache("skip_extra_repos")
def _find_apkbuilds(skip_extra_repos: bool = False) -> dict[str, Path]:
@Cache("with_extra_repos")
def _find_apkbuilds(with_extra_repos: WithExtraRepos = "default") -> dict[str, Path]:
apkbuilds = {}
for package in pkgrepo_iter_package_dirs(skip_extra_repos=skip_extra_repos):
for package in pkgrepo_iter_package_dirs(with_extra_repos=with_extra_repos):
pkgname = package.name
if pkgname in apkbuilds:
raise RuntimeError(
@ -139,8 +140,8 @@ def _find_package_in_apkbuild(package: str, path: Path) -> bool:
return False
@Cache("package", "subpackages", skip_extra_repos=False)
def find(package, must_exist=True, subpackages=True, skip_extra_repos=False):
@Cache("package", "subpackages", "with_extra_repos")
def find(package, must_exist=True, subpackages=True, with_extra_repos="default"):
"""Find the directory in pmaports that provides a package or subpackage.
If you want the parsed APKBUILD instead, use pmb.helpers.pmaports.get().
@ -161,7 +162,7 @@ def find(package, must_exist=True, subpackages=True, skip_extra_repos=False):
raise RuntimeError("Invalid pkgname: " + package)
# Try to find an APKBUILD with the exact pkgname we are looking for
path = _find_apkbuilds(skip_extra_repos).get(package)
path = _find_apkbuilds(with_extra_repos).get(package)
if path:
logging.verbose(f"{package}: found apkbuild: {path}")
ret = path.parent
@ -203,9 +204,12 @@ def find_optional(package: str) -> Path | None:
# The only caller with subpackages=False is ui.check_option()
@Cache("pkgname", subpackages=True)
@Cache("pkgname", "with_extra_repos", subpackages=True)
def get_with_path(
pkgname: str, must_exist: bool = True, subpackages: bool = True, skip_extra_repos: bool = False
pkgname: str,
must_exist: bool = True,
subpackages: bool = True,
with_extra_repos: WithExtraRepos = "default",
) -> tuple[Path | None, dict[str, Any] | None]:
"""Find and parse an APKBUILD file.
@ -216,7 +220,7 @@ def get_with_path(
:param must_exist: raise an exception when it can't be found
:param subpackages: also search for subpackages with the specified
names (slow! might need to parse all APKBUILDs to find it)
:param skip_extra_repos: skip extra repositories (e.g. systemd) when
:param with_extra_repos: use extra repositories (e.g. systemd) when
searching for the package
:returns: relevant variables from the APKBUILD as dictionary, e.g.:
@ -228,16 +232,19 @@ def get_with_path(
... }
"""
pkgname = pmb.helpers.package.remove_operators(pkgname)
pmaport = find(pkgname, must_exist, subpackages, skip_extra_repos)
pmaport = find(pkgname, must_exist, subpackages, with_extra_repos)
if pmaport:
return pmaport, pmb.parse.apkbuild(pmaport / "APKBUILD")
return None, None
def get(
pkgname: str, must_exist: bool = True, subpackages: bool = True, skip_extra_repos: bool = False
pkgname: str,
must_exist: bool = True,
subpackages: bool = True,
with_extra_repos: WithExtraRepos = "default",
) -> dict[str, Any]:
return get_with_path(pkgname, must_exist, subpackages, skip_extra_repos)[1]
return get_with_path(pkgname, must_exist, subpackages, with_extra_repos)[1]
def find_providers(provide: str, default: list[str]) -> list[tuple[Any, Any]]:

View file

@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
import os
from pmb.core.pkgrepo import pkgrepo_iglob
from pmb.types import WithExtraRepos
import pmb.helpers.pmaports
import pmb.helpers.package
import pmb.parse
@ -29,7 +30,7 @@ def list_ui(arch):
return ret
def check_option(ui, option, skip_extra_repos=False):
def check_option(ui: str, option: str, with_extra_repos: WithExtraRepos = "default") -> bool:
"""
Check if an option, such as pmb:systemd, is inside an UI's APKBUILD.
"""
@ -40,6 +41,6 @@ def check_option(ui, option, skip_extra_repos=False):
pkgname = f"postmarketos-ui-{ui}"
apkbuild = pmb.helpers.pmaports.get(
pkgname, subpackages=False, skip_extra_repos=skip_extra_repos
pkgname, subpackages=False, with_extra_repos=with_extra_repos
)
return option in apkbuild["options"]

View file

@ -16,6 +16,7 @@ RunReturnType = str | int | subprocess.Popen
PathString = Path | str
Env = dict[str, PathString]
Apkbuild = dict[str, Any]
WithExtraRepos = Literal["default", "enabled", "disabled"]
# These types are not definitive / API, they exist to describe the current
# state of things so that we can improve our type hinting coverage and make