diff --git a/pmb/config/other.py b/pmb/config/other.py index 4fc1d38f..2f5a37d6 100644 --- a/pmb/config/other.py +++ b/pmb/config/other.py @@ -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]: diff --git a/pmb/core/pkgrepo.py b/pmb/core/pkgrepo.py index 28e420fc..8cfe96a5 100644 --- a/pmb/core/pkgrepo.py +++ b/pmb/core/pkgrepo.py @@ -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: - return paths + 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 diff --git a/pmb/core/test_pkgrepo.py b/pmb/core/test_pkgrepo.py index 30133d9e..124dd70d 100644 --- a/pmb/core/test_pkgrepo.py +++ b/pmb/core/test_pkgrepo.py @@ -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 diff --git a/pmb/helpers/pmaports.py b/pmb/helpers/pmaports.py index 22d74765..6f92e425 100644 --- a/pmb/helpers/pmaports.py +++ b/pmb/helpers/pmaports.py @@ -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]]: diff --git a/pmb/helpers/ui.py b/pmb/helpers/ui.py index 250e250b..5eeb88d5 100644 --- a/pmb/helpers/ui.py +++ b/pmb/helpers/ui.py @@ -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"] diff --git a/pmb/types.py b/pmb/types.py index cdf3d274..1c8f0be9 100644 --- a/pmb/types.py +++ b/pmb/types.py @@ -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