diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py index 6982468df..7d383b552 100644 --- a/src/modules/packages/main.py +++ b/src/modules/packages/main.py @@ -151,6 +151,82 @@ class PackageManager(metaclass=abc.ABCMeta): self.remove([packagedata["package"]]) self.run(packagedata["post-script"]) + def operation_install(self, package_list, from_local=False): + """ + Installs the list of packages named in @p package_list . + These can be strings -- plain package names -- or + structures (with a pre- and post-install step). + + This operation is called for "critical" packages, + which are expected to succeed, or fail, all together. + However, if there are packages with pre- or post-scripts, + then packages are installed one-by-one instead. + + NOTE: package managers may reimplement this method + NOTE: exceptions are expected to leave this method, to indicate + failure of the installation. + """ + if all([isinstance(x, str) for x in package_list]): + self.install(package_list, from_local=from_local) + else: + for package in package_list: + self.install_package(package, from_local=from_local) + + def operation_try_install(self, package_list): + """ + Installs the list of packages named in @p package_list . + These can be strings -- plain package names -- or + structures (with a pre- and post-install step). + + This operation is called for "non-critical" packages, + which can succeed or fail without affecting the overall installation. + Packages are installed one-by-one to support package managers + that do not have a "install as much as you can" mode. + + NOTE: package managers may reimplement this method + NOTE: no package-installation exceptions should be raised + """ + # we make a separate package manager call for each package so a + # single failing package won't stop all of them + for package in package_list: + try: + self.install_package(package) + except subprocess.CalledProcessError: + libcalamares.utils.warning("Could not install package %s" % package) + + def operation_remove(self, package_list): + """ + Removes the list of packages named in @p package_list . + These can be strings -- plain package names -- or + structures (with a pre- and post-install step). + + This operation is called for "critical" packages, which are + expected to succeed or fail all together. + However, if there are packages with pre- or post-scripts, + then packages are removed one-by-one instead. + + NOTE: package managers may reimplement this method + NOTE: exceptions should be raised to indicate failure + """ + if all([isinstance(x, str) for x in package_list]): + self.remove(package_list) + else: + for package in package_list: + self.remove_package(package) + + def operation_try_remove(self, package_list): + """ + Same relation as try_install has to install, except it removes + packages instead. Packages are removed one-by-one. + + NOTE: package managers may reimplement this method + NOTE: no package-installation exceptions should be raised + """ + for package in package_list: + try: + self.remove_package(package) + except subprocess.CalledProcessError: + libcalamares.utils.warning("Could not remove package %s" % package) ### PACKAGE MANAGER IMPLEMENTATIONS # @@ -503,45 +579,19 @@ def run_operations(pkgman, entry): group_packages = len(package_list) if key == "install": _change_mode(INSTALL) - if all([isinstance(x, str) for x in package_list]): - pkgman.install(package_list) - else: - for package in package_list: - pkgman.install_package(package) + pkgman.operation_install(package_list) elif key == "try_install": _change_mode(INSTALL) - # we make a separate package manager call for each package so a - # single failing package won't stop all of them - for package in package_list: - try: - pkgman.install_package(package) - except subprocess.CalledProcessError: - warn_text = "Could not install package " - warn_text += str(package) - libcalamares.utils.warning(warn_text) + pkgman.operation_try_install(package_list) elif key == "remove": _change_mode(REMOVE) - if all([isinstance(x, str) for x in package_list]): - pkgman.remove(package_list) - else: - for package in package_list: - pkgman.remove_package(package) + pkgman.operation_remove(package_list) elif key == "try_remove": _change_mode(REMOVE) - for package in package_list: - try: - pkgman.remove_package(package) - except subprocess.CalledProcessError: - warn_text = "Could not remove package " - warn_text += str(package) - libcalamares.utils.warning(warn_text) + pkgman.operation_try_remove(package_list) elif key == "localInstall": _change_mode(INSTALL) - if all([isinstance(x, str) for x in package_list]): - pkgman.install(package_list, from_local=True) - else: - for package in package_list: - pkgman.install_package(package, from_local=True) + pkgman.operation_install(package_list, from_local=True) elif key == "source": libcalamares.utils.debug("Package-list from {!s}".format(entry[key])) else: