From 401233a352c04aae0a9aa0c0ca0a6d89a09c5af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vid=20Groniewsky?= Date: Mon, 29 Sep 2025 14:57:34 +0200 Subject: [PATCH] Added support for declaring installed and ignored flatpaks in the source file. For this the variables 'flatpak_packages' and 'ignored_flatpak_packages' are used. These work like the pacman equivalents. There were test cases appended for flatpak testing. I have installed the modified version on my system and tested it extensively. No errors were found. --- dist/decman-0.3.4-py3-none-any.whl | Bin 0 -> 50426 bytes src/decman/__init__.py | 2 + src/decman/app.py | 69 +++++++++++++---- src/decman/config.py | 31 ++++++++ src/decman/lib/__init__.py | 115 +++++++++++++++++++++++++++++ tests/test_source_resolution.py | 77 ++++++++----------- 6 files changed, 235 insertions(+), 59 deletions(-) create mode 100644 dist/decman-0.3.4-py3-none-any.whl diff --git a/dist/decman-0.3.4-py3-none-any.whl b/dist/decman-0.3.4-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..ac2a02232ab1e27ff99184ff1ec9fb35e2a264cf GIT binary patch literal 50426 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 &Mqwl-oZTQD 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%0DC4tV)(l;Vbe%Q@~ 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 literal 0 HcmV?d00001 diff --git a/src/decman/__init__.py b/src/decman/__init__.py index 99ba5dd..c1c341d 100644 --- a/src/decman/__init__.py +++ b/src/decman/__init__.py @@ -412,3 +412,5 @@ enabled_systemd_user_units: dict[str, list[str]] = {} files: dict[str, File] = {} directories: dict[str, Directory] = {} modules: list[Module] = [] +flatpak_packages: list[str] = [] +ignored_flatpak_packages: list[str] = [] diff --git a/src/decman/app.py b/src/decman/app.py index 053c51d..04854c1 100644 --- a/src/decman/app.py +++ b/src/decman/app.py @@ -205,6 +205,7 @@ class Core: self.store = store self.source = _resolve_source() self.pacman = l.Pacman() + self.flatpak = l.Flatpak() self.systemctl = l.Systemd(store) self.fpkg_search = fpm.ExtendedPackageSearch(self.pacman) @@ -257,36 +258,76 @@ class Core: self.systemctl.disable_user_units(units, user) def _remove_pkgs(self): + """ + Remove pacman and flatpak packages + """ + # pacman currently_installed = self.pacman.get_installed() to_remove = self.source.packages_to_remove(currently_installed) - l.print_list("Removing packages:", to_remove) - if not self.only_print: - self.pacman.remove(to_remove) + + currently_installed_flatpak = self.flatpak.get_installed() + to_remove_flatpak = self.source.flatpak_packages_to_remove( + currently_installed_flatpak + ) + + l.print_list("Removing pacman packages:", to_remove) + l.print_list("Removing flatpak packages:", to_remove_flatpak) + + if self.only_print: + return + + self.pacman.remove(to_remove) + + # flatpak + self.flatpak.remove(to_remove_flatpak) def _upgrade_pkgs(self): + """ + Upgrade pacman, fpm and flatpak packages + """ + # flatpak + fpm l.print_summary("Upgrading packages.") - if not self.only_print: - self.pacman.upgrade() - if conf.enable_fpm and self.update_foreign_packages: - self.fpm.upgrade( - self.upgrade_devel, self.force_build, self.source.ignored_packages - ) + if self.only_print: + return + + self.pacman.upgrade() + if conf.enable_fpm and self.update_foreign_packages: + self.fpm.upgrade( + self.upgrade_devel, self.force_build, self.source.ignored_packages + ) + + # flatpak + self.flatpak.upgrade() def _install_pkgs(self): + """ + Installs all pacman, fpm, and flatpak packages. + """ + + # pacman + fpm currently_installed = self.pacman.get_installed() to_install_pacman = self.source.pacman_packages_to_install(currently_installed) to_install_fpm = self.source.foreign_packages_to_install(currently_installed) + # flatpak + currently_installed_flatpak = self.flatpak.get_installed() + to_install_flatpak = self.source.flatpak_packages_to_install( + currently_installed_flatpak + ) + l.print_list("Installing pacman packages:", to_install_pacman) + l.print_list("Installing flatpak packages:", to_install_flatpak) # fpm prints a summary so no need to print it twice if self.only_print: l.print_list("Installing foreign packages:", to_install_fpm) + return - if not self.only_print: - self.pacman.install(to_install_pacman) - if conf.enable_fpm and self.update_foreign_packages: - self.fpm.install(to_install_fpm, force=self.force_build) + self.pacman.install(to_install_pacman) + if conf.enable_fpm and self.update_foreign_packages: + self.fpm.install(to_install_fpm, force=self.force_build) + + self.flatpak.install(to_install_flatpak) def _create_and_remove_files(self): l.print_summary("Installing files.") @@ -356,6 +397,8 @@ def _resolve_source() -> l.Source: files=decman.files, directories=decman.directories, modules=set(decman.modules), + flatpak_packages=set(decman.flatpak_packages), + ignored_flatpak_packages=set(decman.ignored_flatpak_packages), ) diff --git a/src/decman/config.py b/src/decman/config.py index 4c1c794..bb9686f 100644 --- a/src/decman/config.py +++ b/src/decman/config.py @@ -34,6 +34,13 @@ class Commands: """ return ["pacman", "-Qeq", "--color=never"] + def list_flatpak_pkgs(self) -> list[str]: + """ + Running this command outputs a newline separated list of installed flatpak application ids + The first line just says 'Application ID' so this one is ignored. + """ + return ["flatpak", "list", "--app", "--columns", "application"] + def list_foreign_pkgs_versioned(self) -> list[str]: """ Running this command outputs a newline seperated list of installed packages and their @@ -47,6 +54,12 @@ class Commands: """ return ["pacman", "-S", "--color=always", "--needed"] + pkgs + def install_flatpak_pkgs(self, pkgs: list[str]) -> list[str]: + """ + Running this command installs all listed packages, and their dependencies/runtimes automatically. + """ + return ["flatpak", "install"] + pkgs + def install_files(self, pkg_files: list[str]) -> list[str]: """ Running this command installs the given packages files. @@ -78,6 +91,12 @@ class Commands: """ return ["pacman", "-Syu", "--color=always"] + def upgrade_flatpak(self) -> list[str]: + """ + Updates all installed flatpak REFs including runtimes and dependencies. + """ + return ["flatpak", "update"] + def remove(self, pkgs: list[str]) -> list[str]: """ Running this command removes the given packages and their dependencies @@ -85,6 +104,18 @@ class Commands: """ return ["pacman", "-Rs", "--color=always"] + pkgs + def remove_flatpak(self, pkgs: list[str]) -> list[str]: + """ + Running this command will remove the listed REFs. Unused dependencies might be kept, but to remove them another command needs to be run. + """ + return ["flatpak", "remove"] + pkgs + + def remove_unused_flatpak(self) -> list[str]: + """ + This will remove all unused flatpak dependencies and runtimes. + """ + return ["flatpak", "remove", "--unused"] + def enable_units(self, units: list[str]) -> list[str]: """ Running this command enables the given systemd units. diff --git a/src/decman/lib/__init__.py b/src/decman/lib/__init__.py index 46d711e..7719764 100644 --- a/src/decman/lib/__init__.py +++ b/src/decman/lib/__init__.py @@ -419,6 +419,8 @@ class Source: files: dict[str, decman.File], directories: dict[str, decman.Directory], modules: set[decman.Module], + flatpak_packages: set[str], + ignored_flatpak_packages: set[str], ): self.pacman_packages = pacman_packages self.aur_packages = aur_packages @@ -429,6 +431,8 @@ class Source: self.files = files self.directories = directories self.modules = modules + self.flatpak_packages = flatpak_packages + self.ignored_flatpak_packages = ignored_flatpak_packages def run_on_enable(self, store: Store): """ @@ -639,6 +643,36 @@ class Source: result.append(pkg) return result + def flatpak_packages_to_install( + self, currently_installed_packages: list[str] + ) -> list[str]: + """ + Returns all flatpak packages, that are not installed or ignored + """ + + result: list[str] = [] + for pkg in self.flatpak_packages: + if pkg in self.ignored_flatpak_packages: + continue + if pkg not in currently_installed_packages: + result.append(pkg) + return result + + def flatpak_packages_to_remove( + self, currently_installed_packages: list[str] + ) -> list[str]: + """ + This returns a list of flatpak app ids, that need to be removed since they are installed but not found in either the list of ignored packages or the list of flatpak packages that need to be installed. + """ + result: list[str] = [] + for package in currently_installed_packages: + if package in self.ignored_flatpak_packages: + continue + if package not in self.flatpak_packages: + result.append(package) + + return result + def all_enabled_modules(self) -> list[tuple[str, str]]: """ Returns all enabled modules and their versions. @@ -922,6 +956,87 @@ def echo_and_capture_command(program: list[str]) -> tuple[int, str]: return (returncode, output) +class Flatpak: + def __init__(self) -> None: + pass + + def get_installed(self) -> list[str]: + """ + Return all of the installed applications. Dependencies and runtimes are exluded since they will not be explicitly installed and thus flatpak will manage them. + """ + try: + packages = ( + subprocess.run( + conf.commands.list_flatpak_pkgs(), + check=True, + stdout=subprocess.PIPE, + ) + .stdout.decode() + .strip() + .split("\n") + ) + + # The header might be included. It might also not. This will make sure that it is not present. + if "Application ID" in packages: + packages.remove("Application ID") + + return packages + except subprocess.CalledProcessError as error: + raise err.UserFacingError( + user_facing_msg=f"Failed to get installed flatpak packages using '{error.cmd}'. Output: {error.stdout}." + ) from error + + def install(self, packages: list[str]): + """ + Install the listed flatpak packages. + """ + if not packages: + return + + returncode, _output = echo_and_capture_command( + conf.commands.install_flatpak_pkgs(packages) + ) + if returncode != 0: + raise err.UserFacingError( + f"Failed to install flatpak packages. Process exited with code {returncode}." + ) + + def upgrade(self) -> None: + """ + Upgrade all flatpak packages. + """ + returncode, _output = echo_and_capture_command(conf.commands.upgrade_flatpak()) + if not returncode == 0: + raise err.UserFacingError( + f"Failed to upgrade flatpak packages. Process exited with code {returncode}." + ) + + def remove(self, packages: list[str]): + """ + Remove all the listed packages and their unused dependecies. This has to happen in two steps. + """ + if not packages: + return + + returncode, _output = echo_and_capture_command( + conf.commands.remove_flatpak(packages) + ) + + if not returncode == 0: + raise err.UserFacingError( + f"Failed to remove flatpak packages. Process exited with code {returncode}." + ) + + returncode, _output = echo_and_capture_command( + conf.commands.remove_unused_flatpak() + ) + + if not returncode == 0: + raise err.UserFacingError( + f"Failed to remove unused flatpak packages. Process exited with code {returncode}." + ) + + class Systemd: """ Interface for interacting with systemd. diff --git a/tests/test_source_resolution.py b/tests/test_source_resolution.py index c4c887c..8b98577 100644 --- a/tests/test_source_resolution.py +++ b/tests/test_source_resolution.py @@ -6,7 +6,6 @@ from decman import UserPackage, Module class ExistingTestModule(Module): - def __init__(self): self.on_enable_executed = False self.on_disable_executed = False @@ -28,7 +27,6 @@ class ExistingTestModule(Module): class ExistingChangedVersionTestModule(Module): - def __init__(self): self.on_enable_executed = False self.on_disable_executed = False @@ -50,7 +48,6 @@ class ExistingChangedVersionTestModule(Module): class EnabledTestModule(Module): - def __init__(self): self.on_enable_executed = False self.on_disable_executed = False @@ -78,7 +75,6 @@ class EnabledTestModule(Module): class DisabledTestModule(Module): - def __init__(self): self.on_enable_executed = False self.on_disable_executed = False @@ -106,7 +102,6 @@ class DisabledTestModule(Module): class TestSource(unittest.TestCase): - def setUp(self): self.disabled_module = DisabledTestModule() self.enabled_module = EnabledTestModule() @@ -133,7 +128,7 @@ class TestSource(unittest.TestCase): version="1", dependencies=["d2"], git_url="/am/url/yes", - ) + ), }, ignored_packages={"i1", "i2"}, systemd_units={"1.service", "2.timer"}, @@ -141,11 +136,12 @@ class TestSource(unittest.TestCase): modules=modules, files={}, directories={}, + flatpak_packages={"f1", "f2", "f3"}, + ignored_flatpak_packages={"i1", "i2"}, ) store = Store() - store.enabled_systemd_units.extend( - ["1.service", "3.service", "M_1.service"]) + store.enabled_systemd_units.extend(["1.service", "3.service", "M_1.service"]) store.add_enabled_user_systemd_unit("user", "u1.service") store.add_enabled_user_systemd_unit("user", "u3.service") store.enabled_modules = { @@ -174,16 +170,19 @@ class TestSource(unittest.TestCase): self.currently_installed_packages = currently_installed_packages def test_all_enabled_modules(self): - enabled_modules = [("Enabled", "1"), ("Existing", "1"), - ("ExistingChanged", "2")] - self.assertCountEqual(self.source.all_enabled_modules(), - enabled_modules) + enabled_modules = [ + ("Enabled", "1"), + ("Existing", "1"), + ("ExistingChanged", "2"), + ] + self.assertCountEqual(self.source.all_enabled_modules(), enabled_modules) def test_files_to_remove(self): created_files = ["/test/file1", "/test/file4"] self.assertCountEqual( self.source.files_to_remove(self.store, created_files), - ["/test/file2", "/test/file3"]) + ["/test/file2", "/test/file3"], + ) def test_after_update_executed(self): self.source.run_after_update() @@ -197,8 +196,7 @@ class TestSource(unittest.TestCase): self.source.run_after_version_change(self.store) self.assertTrue(self.enabled_module.after_version_change_executed) - self.assertTrue( - self.existing_module_changed.after_version_change_executed) + self.assertTrue(self.existing_module_changed.after_version_change_executed) self.assertFalse(self.existing_module.after_version_change_executed) self.assertFalse(self.disabled_module.after_version_change_executed) @@ -233,10 +231,7 @@ class TestSource(unittest.TestCase): def test_user_units_to_enable(self): self.assertDictEqual( self.source.user_units_to_enable(self.store), - { - "user": ["u2.timer"], - "muser": ["M_u1.service"] - }, + {"user": ["u2.timer"], "muser": ["M_u1.service"]}, ) def test_user_units_to_disable(self): @@ -247,15 +242,13 @@ class TestSource(unittest.TestCase): def test_pacman_packages_to_install(self): self.assertCountEqual( - self.source.pacman_packages_to_install( - self.currently_installed_packages), + self.source.pacman_packages_to_install(self.currently_installed_packages), ["p3", "M_p1", "M_p2"], ) def test_foreign_packages_to_install(self): self.assertCountEqual( - self.source.foreign_packages_to_install( - self.currently_installed_packages), + self.source.foreign_packages_to_install(self.currently_installed_packages), ["A1", "U2"], ) @@ -265,46 +258,38 @@ class TestSource(unittest.TestCase): ["p4", "A4", "M_A1", "M_A2"], ) + class TestModuleUserServices(unittest.TestCase): - class ModuleWithUserServiceOne(Module): - def __init__(self): super().__init__("one", True, "0") def systemd_user_units(self) -> dict[str, list[str]]: - return { - "user": ['foo.service'] - } + return {"user": ["foo.service"]} class ModuleWithUserServiceTwo(Module): - def __init__(self): super().__init__("two", True, "0") def systemd_user_units(self) -> dict[str, list[str]]: - return { - "user": ['bar.service'] - } + return {"user": ["bar.service"]} def setUp(self) -> None: self.source = Source( - pacman_packages=set(), - aur_packages=set(), - user_packages=set(), - ignored_packages=set(), - systemd_units=set(), - systemd_user_units={}, - files={}, - directories={}, - modules={ - self.ModuleWithUserServiceOne(), - self.ModuleWithUserServiceTwo() - }, - ) + pacman_packages=set(), + aur_packages=set(), + user_packages=set(), + ignored_packages=set(), + systemd_units=set(), + systemd_user_units={}, + files={}, + directories={}, + modules={self.ModuleWithUserServiceOne(), self.ModuleWithUserServiceTwo()}, + flatpak_packages=set(), + ignored_flatpak_packages=set(), + ) self.store = Store() - def test_user_units_to_enable(self): self.assertDictEqual( self.source.user_units_to_enable(self.store),