pmbootstrap-meow/pmb/helpers/lint.py
Oliver Smith 3ea5a3433b
Revert "pmb: Make RunOutputTypeDefault and RunOutputTypePopen enums"
Revert the patch, as it breaks "pmbootstrap chroot".

This reverts commit 7d2f055bcb.
2025-07-10 23:53:54 +02:00

116 lines
4.2 KiB
Python

# Copyright 2023 Danct12 <danct12@disroot.org>
# SPDX-License-Identifier: GPL-3.0-or-later
from collections.abc import Sequence
from pmb.core.chroot import Chroot
from pmb.core.pkgrepo import (
pkgrepo_iter_package_dirs,
pkgrepo_name,
pkgrepo_names,
pkgrepo_relative_path,
)
from pmb.helpers import logging
from pmb.helpers.exceptions import NonBugError
from pmb.helpers.toml import load_toml_file
import os
import pmb.chroot
import pmb.chroot.apk
import pmb.build
import pmb.helpers.run
import pmb.helpers.pmaports
def get_custom_valid_options() -> list[str]:
"""Build a list of custom valid APKBUILD options that apkbuild-lint should
not complain about. The list consists of hardcoded options from
pmb.config.apkbuild_custom_valid_options like pmb:drm, as well as
dynamically generated options from kconfigcheck.toml
(pmb:kconfigcheck-libcamera etc.)."""
ret = list(pmb.config.apkbuild_custom_valid_options)
# Load kconfigcheck.toml from current branch
kconfigcheck_toml = load_toml_file(pmb.parse.kconfigcheck.get_path())
pmb.parse.kconfigcheck.sanity_check(kconfigcheck_toml)
# Add options like "pmb:kconfigcheck-libcamera"
for section in kconfigcheck_toml.keys():
if not section.startswith("category:"):
continue
# section looks like: "category:input.>=0.0.0.all"
category = section.split(".")[0].replace("category:", "", 1)
ret += [f"pmb:kconfigcheck-{category}"]
# Add aliases like "pmb:kconfigcheck-community"
for alias in kconfigcheck_toml["aliases"].keys():
ret += [f"pmb:kconfigcheck-{alias}"]
return ret
# FIXME: dest_paths[repo], repo expected to be a Literal.
# We should really make Config.mirrors not a TypedDict.
# mypy: disable-error-code="index"
def check(pkgnames: Sequence[str]) -> None:
"""Run apkbuild-lint on the supplied packages.
:param pkgnames: Names of the packages to lint
"""
chroot = Chroot.native()
pmb.chroot.init(chroot)
pmb.chroot.apk.install(["atools"], chroot)
# Mount pmaports.git inside the chroot so that we don't have to copy the
# package folders
dest_paths = pmb.build.mount_pmaports(chroot)
# Locate all APKBUILDs and make the paths be relative to the pmaports
# root
apkbuilds: dict[str, list[str]] = dict(map(lambda x: (x, []), pkgrepo_names()))
found_pkgnames = set()
# If a package exists in multiple aports we will lint all of them
# since.. well, what else do we do?
for pkgdir in pkgrepo_iter_package_dirs():
if pkgdir.name not in pkgnames:
continue
repo, relpath = pkgrepo_relative_path(pkgdir)
apkbuilds[pkgrepo_name(repo)].append(os.fspath(relpath / "APKBUILD"))
found_pkgnames.add(pkgdir.name)
# Check we found all the packages in pkgnames
if len(found_pkgnames) != len(pkgnames):
missing = set(pkgnames) - found_pkgnames
logging.error(f"Could not find the following packages: {missing}")
return
# Run apkbuild-lint in chroot from the pmaports mount point. This will
# print a nice source identifier à la "./cross/grub-x86/APKBUILD" for
# each violation.
pkgstr = ", ".join(pkgnames)
logging.info(f"(native) linting {pkgstr} with apkbuild-lint")
# apkbuild-lint output is not colorized, make it easier to spot
logging.info("*** apkbuild-lint output ***")
# For each pkgrepo run the linter on the relevant packages
has_failed = False
for pkgrepo, apkbuild_paths in apkbuilds.items():
# We search for the pkgnames in both the normal and systemd repository,
# so unless the pkgname exists in both the apkbuild_paths is empty for
# one of them and needs to be skipped here. This is not very elegant,
# let's rework the CI logic for this at some point: pma#3665
if not apkbuild_paths:
continue
if pmb.chroot.user(
["apkbuild-lint", *apkbuild_paths],
check=False,
output="stdout",
working_dir=dest_paths[pkgrepo_name(repo)],
env={"CUSTOM_VALID_OPTIONS": " ".join(get_custom_valid_options())},
):
has_failed = True
logging.info("*** apkbuild-lint output ***")
if has_failed:
raise NonBugError("Linter failed!")