From d8615a9cae6d438c8b03aaa419f1ef5187ed70da Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Mon, 20 Jul 2020 08:57:01 +0200 Subject: [PATCH] pmbootstrap install: support _pmb_recommends (MR 1962) Let UI meta-packages specify apps in "pmb_recommends" to be explicitly installed by default, and not implicitly as dependency of the UI meta-package ("depends"). Therefore make these apps uninstallable, without removing the meta-package. Add pmbootstrap install --no-recommends to disable this feature. --- pmb/config/__init__.py | 7 ++++ pmb/install/_install.py | 33 ++++++++++++++++- pmb/parse/arguments.py | 4 +++ test/test_install.py | 35 +++++++++++++++++++ .../main/postmarketos-ui-test/APKBUILD | 13 +++++++ 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 test/testdata/pmb_recommends/main/postmarketos-ui-test/APKBUILD diff --git a/pmb/config/__init__.py b/pmb/config/__init__.py index 16bd0c00..d73e85b0 100644 --- a/pmb/config/__init__.py +++ b/pmb/config/__init__.py @@ -250,6 +250,13 @@ apkbuild_package_attributes = { "pkgdesc": {}, "depends": {"array": True}, "provides": {"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 + # removing the meta-package. (#1933). To disable this feature, use: + # "pmbootstrap install --no-recommends". + "_pmb_recommends": {"array": True}, } # Variables in APKBUILD files, that get parsed diff --git a/pmb/install/_install.py b/pmb/install/_install.py index 78bc3ee8..48b447b9 100644 --- a/pmb/install/_install.py +++ b/pmb/install/_install.py @@ -101,6 +101,36 @@ def get_kernel_package(args, device): return ["device-" + device + "-kernel-" + args.kernel] +def get_recommends_packages(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 copy_files_from_chroot(args, suffix): """ Copy all files from the rootfs chroot to /mnt/install, except @@ -605,7 +635,8 @@ def install(args): install_packages = (pmb.config.install_device_packages + ["device-" + args.device] + get_kernel_package(args, args.device) + - get_nonfree_packages(args, args.device)) + get_nonfree_packages(args, args.device) + + get_recommends_packages(args)) if not args.install_base: install_packages = [p for p in install_packages if p != "postmarketos-base"] if args.ui.lower() != "none": diff --git a/pmb/parse/arguments.py b/pmb/parse/arguments.py index 253f0666..df2640d1 100644 --- a/pmb/parse/arguments.py +++ b/pmb/parse/arguments.py @@ -565,6 +565,10 @@ def arguments(): install.add_argument("--no-local-pkgs", dest="install_local_pkgs", help="do not install locally compiled packages and" " package signing keys", action="store_false") + install.add_argument("--no-recommends", dest="install_recommends", + help="do not install packages listed in" + " _pmb_recommends of the UI pmaports", + action="store_false") group = install.add_mutually_exclusive_group() group.add_argument("--sparse", help="generate sparse image file" " (even if unsupported by device)", default=None, diff --git a/test/test_install.py b/test/test_install.py index a3a906de..d418d0fe 100644 --- a/test/test_install.py +++ b/test/test_install.py @@ -44,3 +44,38 @@ def test_get_nonfree_packages(args): # Device with non-free userland (but user disabled it init) args.nonfree_userland = False assert func(args, device) == [] + + +def test_get_recommends_packages(args): + args.aports = pmb_test.const.testdata + "/pmb_recommends" + func = pmb.install._install.get_recommends_packages + + # UI: none + args.install_recommends = True + args.ui = "none" + assert func(args) == [] + + # UI: test, --no-recommends + args.install_recommends = False + args.ui = "test" + assert func(args) == [] + + # UI: test, without -extras + args.install_recommends = True + args.ui = "test" + args.ui_extras = False + assert func(args) == ["plasma-camera", "plasma-angelfish"] + + # 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") diff --git a/test/testdata/pmb_recommends/main/postmarketos-ui-test/APKBUILD b/test/testdata/pmb_recommends/main/postmarketos-ui-test/APKBUILD new file mode 100644 index 00000000..5ca94068 --- /dev/null +++ b/test/testdata/pmb_recommends/main/postmarketos-ui-test/APKBUILD @@ -0,0 +1,13 @@ +pkgname=postmarketos-ui-test +pkgver=1 +pkgrel=0 +license="GPL-3.0-or-later" +depends="" +subpackages="$pkgname-extras" +arch="all" + +_pmb_recommends="plasma-camera plasma-angelfish" + +extras() { + _pmb_recommends="buho kaidan" +}