forked from Mirror/pmbootstrap
pmb.install: support pmb_recommends for any package
This refactors the get_recommends function that was originally used for UI packages to support pmb_recommends for any package (and subpackage). Extending pmb_recommends will, for example, help us create better generic device packages [1] and can be used to improve packaging for UIs with shared pmb_recommends[2]. 1. https://gitlab.com/postmarketOS/pmaports/-/merge_requests/4673 2. https://gitlab.com/postmarketOS/pmaports/-/merge_requests/3700 Reviewed-by: Oliver Smith <ollieparanoid@postmarketos.org> Link: https://lists.sr.ht/~postmarketos/pmbootstrap-devel/%3C20240102074605.23248-2-clayton@craftyguy.net%3E
This commit is contained in:
parent
0c0f05caab
commit
19f8a3b8c8
6 changed files with 77 additions and 58 deletions
|
@ -696,9 +696,9 @@ apkbuild_package_attributes = {
|
||||||
"install": {"array": True},
|
"install": {"array": True},
|
||||||
"triggers": {"array": True},
|
"triggers": {"array": True},
|
||||||
|
|
||||||
# UI meta-packages can specify apps in "_pmb_recommends" to be explicitly
|
# Packages can specify soft dependencies in "_pmb_recommends" to be
|
||||||
# installed by default, and not implicitly as dependency of the UI meta-
|
# explicitly installed by default, and not implicitly as a hard dependency
|
||||||
# package ("depends"). This makes these apps uninstallable, without
|
# of the package ("depends"). This makes these apps uninstallable, without
|
||||||
# removing the meta-package. (#1933). To disable this feature, use:
|
# removing the meta-package. (#1933). To disable this feature, use:
|
||||||
# "pmbootstrap install --no-recommends".
|
# "pmbootstrap install --no-recommends".
|
||||||
"_pmb_recommends": {"array": True},
|
"_pmb_recommends": {"array": True},
|
||||||
|
|
|
@ -1068,6 +1068,50 @@ def get_selected_providers(args, packages):
|
||||||
return providers
|
return providers
|
||||||
|
|
||||||
|
|
||||||
|
def get_recommends(args, packages):
|
||||||
|
"""
|
||||||
|
Look through the specified packages and collect additional packages
|
||||||
|
specified under _pmb_recommends in them. This is recursive, so it will
|
||||||
|
dive into packages that are listed under recommends to collect any
|
||||||
|
packages they might also have listed under their own _pmb_recommends.
|
||||||
|
|
||||||
|
If unable to find a given package in aports, it is skipped and no error
|
||||||
|
is raised. This is because the given package might be in a different
|
||||||
|
aports than the one searched by this function. This function makes no
|
||||||
|
attempt to validate that a given package is in *any* available aports
|
||||||
|
repos at installation time.
|
||||||
|
|
||||||
|
If running with pmbootstrap install --no-recommends, this function
|
||||||
|
returns an empty list.
|
||||||
|
|
||||||
|
:returns: list of pkgnames, e.g. ["chatty", "gnome-contacts"] """
|
||||||
|
ret = []
|
||||||
|
if not args.install_recommends:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
for package in packages:
|
||||||
|
# Note that this ignores packages that don't exist. This means they
|
||||||
|
# aren't in pmaports. This is fine, with the assumption that
|
||||||
|
# installation will fail later in some other method if they truly don't
|
||||||
|
# exist in any repo.
|
||||||
|
apkbuild = pmb.helpers.pmaports.get(args, package, must_exist=False)
|
||||||
|
if not apkbuild:
|
||||||
|
continue
|
||||||
|
if package in apkbuild["subpackages"]:
|
||||||
|
# Just focus on the subpackage
|
||||||
|
apkbuild = apkbuild["subpackages"][package]
|
||||||
|
recommends = apkbuild["_pmb_recommends"]
|
||||||
|
if recommends:
|
||||||
|
logging.debug(f"{package}: install _pmb_recommends:"
|
||||||
|
f" {', '.join(recommends)}")
|
||||||
|
ret += recommends
|
||||||
|
# Call recursively in case recommends have pmb_recommends of their
|
||||||
|
# own.
|
||||||
|
ret += get_recommends(args, recommends)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def create_device_rootfs(args, step, steps):
|
def create_device_rootfs(args, step, steps):
|
||||||
# List all packages to be installed (including the ones specified by --add)
|
# List all packages to be installed (including the ones specified by --add)
|
||||||
# and upgrade the installed packages/apkindexes
|
# and upgrade the installed packages/apkindexes
|
||||||
|
@ -1096,8 +1140,6 @@ def create_device_rootfs(args, step, steps):
|
||||||
if args.ui.lower() != "none":
|
if args.ui.lower() != "none":
|
||||||
if args.ui_extras:
|
if args.ui_extras:
|
||||||
install_packages += ["postmarketos-ui-" + args.ui + "-extras"]
|
install_packages += ["postmarketos-ui-" + args.ui + "-extras"]
|
||||||
if args.install_recommends:
|
|
||||||
install_packages += pmb.install.ui.get_recommends(args)
|
|
||||||
if args.extra_packages.lower() != "none":
|
if args.extra_packages.lower() != "none":
|
||||||
install_packages += args.extra_packages.split(",")
|
install_packages += args.extra_packages.split(",")
|
||||||
if args.add:
|
if args.add:
|
||||||
|
@ -1126,6 +1168,9 @@ def create_device_rootfs(args, step, steps):
|
||||||
|
|
||||||
pmb.helpers.repo.update(args, args.deviceinfo["arch"])
|
pmb.helpers.repo.update(args, args.deviceinfo["arch"])
|
||||||
|
|
||||||
|
# Install uninstallable "dependencies" by default
|
||||||
|
install_packages += get_recommends(args, install_packages)
|
||||||
|
|
||||||
# Explicitly call build on the install packages, to re-build them or any
|
# Explicitly call build on the install packages, to re-build them or any
|
||||||
# dependency, in case the version increased
|
# dependency, in case the version increased
|
||||||
if args.build_pkgs_on_install:
|
if args.build_pkgs_on_install:
|
||||||
|
|
|
@ -5,36 +5,6 @@ import logging
|
||||||
import pmb.helpers.pmaports
|
import pmb.helpers.pmaports
|
||||||
|
|
||||||
|
|
||||||
def get_recommends(args):
|
|
||||||
""" Get all packages listed in _pmb_recommends of the UI and UI-extras
|
|
||||||
package, unless running with pmbootstrap install --no-recommends.
|
|
||||||
|
|
||||||
:returns: list of pkgnames, e.g. ["chatty", "gnome-contacts"] """
|
|
||||||
ret = []
|
|
||||||
if not args.install_recommends or args.ui == "none":
|
|
||||||
return ret
|
|
||||||
|
|
||||||
# UI package
|
|
||||||
meta = f"postmarketos-ui-{args.ui}"
|
|
||||||
apkbuild = pmb.helpers.pmaports.get(args, meta)
|
|
||||||
recommends = apkbuild["_pmb_recommends"]
|
|
||||||
if recommends:
|
|
||||||
logging.debug(f"{meta}: install _pmb_recommends:"
|
|
||||||
f" {', '.join(recommends)}")
|
|
||||||
ret += recommends
|
|
||||||
|
|
||||||
# UI-extras subpackage
|
|
||||||
meta_extras = f"{meta}-extras"
|
|
||||||
if args.ui_extras and meta_extras in apkbuild["subpackages"]:
|
|
||||||
recommends = apkbuild["subpackages"][meta_extras]["_pmb_recommends"]
|
|
||||||
if recommends:
|
|
||||||
logging.debug(f"{meta_extras}: install _pmb_recommends:"
|
|
||||||
f" {', '.join(recommends)}")
|
|
||||||
ret += recommends
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def get_groups(args):
|
def get_groups(args):
|
||||||
""" Get all groups to which the user additionally must be added.
|
""" Get all groups to which the user additionally must be added.
|
||||||
The list of groups are listed in _pmb_groups of the UI and
|
The list of groups are listed in _pmb_groups of the UI and
|
||||||
|
|
|
@ -50,37 +50,33 @@ def test_get_nonfree_packages(args):
|
||||||
|
|
||||||
def test_get_recommends(args):
|
def test_get_recommends(args):
|
||||||
args.aports = pmb_test.const.testdata + "/pmb_recommends"
|
args.aports = pmb_test.const.testdata + "/pmb_recommends"
|
||||||
func = pmb.install.ui.get_recommends
|
func = pmb.install._install.get_recommends
|
||||||
|
|
||||||
# UI: none
|
# UI: none
|
||||||
args.install_recommends = True
|
args.install_recommends = True
|
||||||
args.ui = "none"
|
assert func(args, ["postmarketos-ui-none"]) == []
|
||||||
assert func(args) == []
|
|
||||||
|
|
||||||
# UI: test, --no-recommends
|
# UI: test, --no-recommends
|
||||||
args.install_recommends = False
|
args.install_recommends = False
|
||||||
args.ui = "test"
|
assert func(args, ["postmarketos-ui-test"]) == []
|
||||||
assert func(args) == []
|
|
||||||
|
|
||||||
# UI: test, without -extras
|
# UI: test
|
||||||
|
args.install_recommends = True
|
||||||
|
assert func(args, ["postmarketos-ui-test"]) == ["plasma-camera",
|
||||||
|
"plasma-angelfish"]
|
||||||
|
|
||||||
|
# UI: test + test-extras
|
||||||
|
args.install_recommends = True
|
||||||
|
assert func(args, ["postmarketos-ui-test",
|
||||||
|
"postmarketos-ui-test-extras"]) == ["plasma-camera",
|
||||||
|
"plasma-angelfish",
|
||||||
|
"buho", "kaidan",
|
||||||
|
"test-app", "foot",
|
||||||
|
"htop"]
|
||||||
|
# Non-UI package
|
||||||
args.install_recommends = True
|
args.install_recommends = True
|
||||||
args.ui = "test"
|
|
||||||
args.ui_extras = False
|
args.ui_extras = False
|
||||||
assert func(args) == ["plasma-camera", "plasma-angelfish"]
|
assert func(args, ["test-app"]) == ["foot", "htop"]
|
||||||
|
|
||||||
# UI: test, with -extras
|
|
||||||
args.install_recommends = True
|
|
||||||
args.ui = "test"
|
|
||||||
args.ui_extras = True
|
|
||||||
assert func(args) == ["plasma-camera", "plasma-angelfish", "buho",
|
|
||||||
"kaidan"]
|
|
||||||
|
|
||||||
# UI: invalid
|
|
||||||
args.install_recommends = True
|
|
||||||
args.ui = "invalid"
|
|
||||||
with pytest.raises(RuntimeError) as e:
|
|
||||||
func(args)
|
|
||||||
assert str(e.value).startswith("Could not find aport for package")
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_groups(args):
|
def test_get_groups(args):
|
||||||
|
|
|
@ -9,5 +9,5 @@ arch="all"
|
||||||
_pmb_recommends="plasma-camera plasma-angelfish"
|
_pmb_recommends="plasma-camera plasma-angelfish"
|
||||||
|
|
||||||
extras() {
|
extras() {
|
||||||
_pmb_recommends="buho kaidan"
|
_pmb_recommends="buho kaidan test-app"
|
||||||
}
|
}
|
||||||
|
|
8
test/testdata/pmb_recommends/main/test-app/APKBUILD
vendored
Normal file
8
test/testdata/pmb_recommends/main/test-app/APKBUILD
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
pkgname=test-app
|
||||||
|
pkgver=1
|
||||||
|
pkgrel=0
|
||||||
|
license="GPL-3.0-or-later"
|
||||||
|
depends=""
|
||||||
|
arch="all"
|
||||||
|
|
||||||
|
_pmb_recommends="foot htop"
|
Loading…
Add table
Add a link
Reference in a new issue