forked from Mirror/pmbootstrap
pmbootstrap lint: avoid looping and copying files (MR 2100)
Before this commit, package folders were copied into the chroot one by one in order to run apkbuild-lint on them. This logic is replaced by mounting pmaports.git into the chroot and using a single apkbuild-lint invocation to lint the supplied packages. Both of these changes result in a performance improvement, especially when linting multiple packages at once. Before this change: $ time ./pmbootstrap.py -q lint $(cd ../pmaports/cross; echo *) \ > /dev/null real 0m5,261s user 0m7,046s sys 0m1,842s Using the pmaports.git mount but calling apkbuild-lint in a loop: $ time ./pmbootstrap.py -q lint $(cd ../pmaports/cross; echo *) \ > /dev/null real 0m4,089s user 0m6,418s sys 0m1,219s After this change: $ time ./pmbootstrap.py -q lint $(cd ../pmaports/cross; echo *) \ > /dev/null real 0m3,518s user 0m5,968s sys 0m0,959s Additionally, running apkbuild-lint from the pmaports.git mount point has the benefit that every printed violation contains a nice source identifier à la "./cross/grub-x86/APKBUILD". This makes it possible to differentiate between different packages even though only a single apkbuild-lint invocation is used. Relates: postmarketOS/pmaports#564
This commit is contained in:
parent
0b95779e30
commit
ac4c967e18
5 changed files with 48 additions and 16 deletions
|
@ -6,4 +6,4 @@ from pmb.build.menuconfig import menuconfig
|
||||||
from pmb.build.newapkbuild import newapkbuild
|
from pmb.build.newapkbuild import newapkbuild
|
||||||
from pmb.build.other import copy_to_buildpath, is_necessary, \
|
from pmb.build.other import copy_to_buildpath, is_necessary, \
|
||||||
index_repo
|
index_repo
|
||||||
from pmb.build._package import package
|
from pmb.build._package import mount_pmaports, package
|
||||||
|
|
|
@ -330,6 +330,16 @@ def override_source(args, apkbuild, pkgver, src, suffix="native"):
|
||||||
pmb.chroot.user(args, ["mv", append_path + "_", apkbuild_path], suffix)
|
pmb.chroot.user(args, ["mv", append_path + "_", apkbuild_path], suffix)
|
||||||
|
|
||||||
|
|
||||||
|
def mount_pmaports(args, destination, suffix="native"):
|
||||||
|
"""
|
||||||
|
Mount pmaports.git in chroot.
|
||||||
|
|
||||||
|
:param destination: mount point inside the chroot
|
||||||
|
"""
|
||||||
|
outside_destination = args.work + "/chroot_" + suffix + destination
|
||||||
|
pmb.helpers.mount.bind(args, args.aports, outside_destination, umount=True)
|
||||||
|
|
||||||
|
|
||||||
def link_to_git_dir(args, suffix):
|
def link_to_git_dir(args, suffix):
|
||||||
"""
|
"""
|
||||||
Make /home/pmos/build/.git point to the .git dir from pmaports.git, with a
|
Make /home/pmos/build/.git point to the .git dir from pmaports.git, with a
|
||||||
|
@ -350,13 +360,12 @@ def link_to_git_dir(args, suffix):
|
||||||
# initialization of the chroot, because the pmaports dir may not exist yet
|
# initialization of the chroot, because the pmaports dir may not exist yet
|
||||||
# at that point. Use umount=True, so we don't have an old path mounted
|
# at that point. Use umount=True, so we don't have an old path mounted
|
||||||
# (some tests change the pmaports dir).
|
# (some tests change the pmaports dir).
|
||||||
inside_destination = "/mnt/pmaports"
|
destination = "/mnt/pmaports"
|
||||||
outside_destination = args.work + "/chroot_" + suffix + inside_destination
|
mount_pmaports(args, destination, suffix)
|
||||||
pmb.helpers.mount.bind(args, args.aports, outside_destination, umount=True)
|
|
||||||
|
|
||||||
# Create .git symlink
|
# Create .git symlink
|
||||||
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/build"], suffix)
|
pmb.chroot.user(args, ["mkdir", "-p", "/home/pmos/build"], suffix)
|
||||||
pmb.chroot.user(args, ["ln", "-sf", inside_destination + "/.git",
|
pmb.chroot.user(args, ["ln", "-sf", destination + "/.git",
|
||||||
"/home/pmos/build/.git"], suffix)
|
"/home/pmos/build/.git"], suffix)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -586,8 +586,7 @@ def lint(args):
|
||||||
if not packages:
|
if not packages:
|
||||||
packages = pmb.helpers.pmaports.get_list(args)
|
packages = pmb.helpers.pmaports.get_list(args)
|
||||||
|
|
||||||
for package in packages:
|
pmb.helpers.lint.check(args, packages)
|
||||||
pmb.helpers.lint.check(args, package)
|
|
||||||
|
|
||||||
|
|
||||||
def status(args):
|
def status(args):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# Copyright 2021 Danct12 <danct12@disroot.org>
|
# Copyright 2021 Danct12 <danct12@disroot.org>
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
import pmb.chroot
|
import pmb.chroot
|
||||||
import pmb.chroot.apk
|
import pmb.chroot.apk
|
||||||
|
@ -9,16 +10,39 @@ import pmb.helpers.run
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
|
||||||
|
|
||||||
def check(args, pkgname):
|
def check(args, pkgnames):
|
||||||
pmb.chroot.apk.install(args, ["atools"])
|
"""
|
||||||
|
Run apkbuild-lint on the supplied packages
|
||||||
|
|
||||||
# Run apkbuild-lint on copy of pmaport in chroot
|
:param pkgnames: Names of the packages to lint
|
||||||
|
"""
|
||||||
|
pmb.chroot.apk.install(args, ["atools"])
|
||||||
pmb.build.init(args)
|
pmb.build.init(args)
|
||||||
pmb.build.copy_to_buildpath(args, pkgname)
|
|
||||||
logging.info("(native) linting " + pkgname + " with apkbuild-lint")
|
# Mount pmaports.git inside the chroot so that we don't have to copy the
|
||||||
|
# package folders
|
||||||
|
pmaports = "/mnt/pmaports"
|
||||||
|
pmb.build.mount_pmaports(args, pmaports)
|
||||||
|
|
||||||
|
# Locate all APKBUILDs and make the paths be relative to the pmaports
|
||||||
|
# root
|
||||||
|
apkbuilds = []
|
||||||
|
for pkgname in pkgnames:
|
||||||
|
aport = pmb.helpers.pmaports.find(args, pkgname)
|
||||||
|
if not os.path.exists(aport + "/APKBUILD"):
|
||||||
|
raise ValueError("Path does not contain an APKBUILD file:" +
|
||||||
|
aport)
|
||||||
|
relpath = os.path.relpath(aport, args.aports)
|
||||||
|
apkbuilds.append(f"{relpath}/APKBUILD")
|
||||||
|
|
||||||
|
# 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")
|
||||||
options = pmb.config.apkbuild_custom_valid_options
|
options = pmb.config.apkbuild_custom_valid_options
|
||||||
return pmb.chroot.user(args, ["apkbuild-lint", "APKBUILD"],
|
return pmb.chroot.root(args, ["apkbuild-lint"] + apkbuilds,
|
||||||
check=False, output="stdout",
|
check=False, output="stdout",
|
||||||
output_return=True,
|
output_return=True,
|
||||||
working_dir="/home/pmos/build",
|
working_dir=pmaports,
|
||||||
env={"CUSTOM_VALID_OPTIONS": " ".join(options)})
|
env={"CUSTOM_VALID_OPTIONS": " ".join(options)})
|
||||||
|
|
|
@ -32,7 +32,7 @@ def test_pmbootstrap_lint(args, tmpdir):
|
||||||
shutil.copyfile(apkbuild_orig, apkbuild_tmp)
|
shutil.copyfile(apkbuild_orig, apkbuild_tmp)
|
||||||
|
|
||||||
# Lint passes
|
# Lint passes
|
||||||
assert pmb.helpers.lint.check(args, "hello-world") == ""
|
assert pmb.helpers.lint.check(args, ["hello-world"]) == ""
|
||||||
|
|
||||||
# Change "pmb:cross-native" to non-existing "pmb:invalid-opt"
|
# Change "pmb:cross-native" to non-existing "pmb:invalid-opt"
|
||||||
pmb.helpers.run.user(args, ["sed", "s/pmb:cross-native/pmb:invalid-opt/g",
|
pmb.helpers.run.user(args, ["sed", "s/pmb:cross-native/pmb:invalid-opt/g",
|
||||||
|
@ -40,4 +40,4 @@ def test_pmbootstrap_lint(args, tmpdir):
|
||||||
|
|
||||||
# Lint error
|
# Lint error
|
||||||
err_str = "invalid option 'pmb:invalid-opt'"
|
err_str = "invalid option 'pmb:invalid-opt'"
|
||||||
assert err_str in pmb.helpers.lint.check(args, "hello-world")
|
assert err_str in pmb.helpers.lint.check(args, ["hello-world"])
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue