M pmb/config/__init__.py => pmb/config/__init__.py +3 -3
@@ 696,9 696,9 @@ apkbuild_package_attributes = {
"install": {"array": True},
"triggers": {"array": True},
- # UI meta-packages can specify apps in "_pmb_recommends" to be explicitly
- # installed by default, and not implicitly as dependency of the UI meta-
- # package ("depends"). This makes these apps uninstallable, without
+ # Packages can specify soft dependencies in "_pmb_recommends" to be
+ # explicitly installed by default, and not implicitly as a hard dependency
+ # of the package ("depends"). This makes these apps uninstallable, without
# removing the meta-package. (#1933). To disable this feature, use:
# "pmbootstrap install --no-recommends".
"_pmb_recommends": {"array": True},
M pmb/install/_install.py => pmb/install/_install.py +47 -2
@@ 1068,6 1068,50 @@ def get_selected_providers(args, packages):
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):
# List all packages to be installed (including the ones specified by --add)
# 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_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":
install_packages += args.extra_packages.split(",")
if args.add:
@@ 1126,6 1168,9 @@ def create_device_rootfs(args, step, steps):
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
# dependency, in case the version increased
if args.build_pkgs_on_install:
M pmb/install/ui.py => pmb/install/ui.py +0 -30
@@ 5,36 5,6 @@ import logging
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):
""" Get all groups to which the user additionally must be added.
The list of groups are listed in _pmb_groups of the UI and
M test/test_install.py => test/test_install.py +16 -20
@@ 50,37 50,33 @@ def test_get_nonfree_packages(args):
def test_get_recommends(args):
args.aports = pmb_test.const.testdata + "/pmb_recommends"
- func = pmb.install.ui.get_recommends
+ func = pmb.install._install.get_recommends
# UI: none
args.install_recommends = True
- args.ui = "none"
- assert func(args) == []
+ assert func(args, ["postmarketos-ui-none"]) == []
# UI: test, --no-recommends
args.install_recommends = False
- args.ui = "test"
- assert func(args) == []
+ assert func(args, ["postmarketos-ui-test"]) == []
- # UI: test, without -extras
+ # UI: test
args.install_recommends = True
- args.ui = "test"
- args.ui_extras = False
- assert func(args) == ["plasma-camera", "plasma-angelfish"]
+ assert func(args, ["postmarketos-ui-test"]) == ["plasma-camera",
+ "plasma-angelfish"]
- # UI: test, with -extras
+ # UI: test + test-extras
args.install_recommends = True
- args.ui = "test"
- args.ui_extras = True
- assert func(args) == ["plasma-camera", "plasma-angelfish", "buho",
- "kaidan"]
-
- # UI: invalid
+ 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.ui = "invalid"
- with pytest.raises(RuntimeError) as e:
- func(args)
- assert str(e.value).startswith("Could not find aport for package")
+ args.ui_extras = False
+ assert func(args, ["test-app"]) == ["foot", "htop"]
def test_get_groups(args):
M test/testdata/pmb_recommends/main/postmarketos-ui-test/APKBUILD => test/testdata/pmb_recommends/main/postmarketos-ui-test/APKBUILD +1 -1
@@ 9,5 9,5 @@ arch="all"
_pmb_recommends="plasma-camera plasma-angelfish"
extras() {
- _pmb_recommends="buho kaidan"
+ _pmb_recommends="buho kaidan test-app"
}
A test/testdata/pmb_recommends/main/test-app/APKBUILD => test/testdata/pmb_recommends/main/test-app/APKBUILD +8 -0
@@ 0,0 1,8 @@
+pkgname=test-app
+pkgver=1
+pkgrel=0
+license="GPL-3.0-or-later"
+depends=""
+arch="all"
+
+_pmb_recommends="foot htop"