diff --git a/changelog.md b/changelog.md index edc0da41f..7c226ef97 100644 --- a/changelog.md +++ b/changelog.md @@ -20,6 +20,7 @@ This version is not released yet and is under active development. - \[mpm\] Remove `-c`/`--cli-format` option. - \[mpm\] Use short-form selection option and fully-qualified path in `mpm`-based upgrade-all CLIs produced by `outdated` command. +- \[mpm\] Add dedicated execution path for running sudo-prefixed commands. - \[mpm\] Fix local overriding of CLI parameters leading to missing `sudo` pre-command. Closes {issue}`579`. - \[mpm\] Use string highlighting code from `click-extra >= 2.1.0`. diff --git a/meta_package_manager/base.py b/meta_package_manager/base.py index 8c831912a..cc6e3e6ef 100644 --- a/meta_package_manager/base.py +++ b/meta_package_manager/base.py @@ -390,6 +390,7 @@ def build_cli( override_cli_path=False, override_pre_args=False, override_post_args=False, + sudo=False, ): """Build the package manager CLI by combining the custom ``*args`` with the PM's global parameters. @@ -402,7 +403,7 @@ def build_cli( .. code-block:: shell-session - $ <*args> + $ [|sudo] <*args> * ``self.pre_cmds`` is added before the CLI path. @@ -418,13 +419,25 @@ def build_cli( Each global set of elements can be locally overriden with: * ``override_pre_cmds=tuple()`` + * ``override_cli_path=str`` * ``override_pre_args=tuple()`` * ``override_post_args=tuple()`` + + On linux, the command can be ran with `sudo` if the parameter of the same name is set to `True`. + In which case `override_pre_cmds` are not allowed and `auto_pre_cmds` is forced to `False`. """ params = [] - # Prepare the full list of CLI arguments. - if override_pre_cmds: + # Sudo replaces any pre-command, be it overriden or automatic. + if sudo: + if not is_linux(): + raise NotImplementedError("sudo only supported on Linux.") + if override_pre_cmds: + raise ValueError("Pre-commands not allowed if sudo is requested.") + if auto_pre_cmds: + auto_pre_cmds = False + params.add("sudo") + elif override_pre_cmds: assert isinstance(override_pre_cmds, tuple) params.extend(override_pre_cmds) elif auto_pre_cmds: @@ -466,6 +479,7 @@ def run_cli( override_pre_args=False, override_post_args=False, force_exec=False, + sudo=False, ): """Build and run the package manager CLI by combining the custom ``*args`` with the PM's global parameters. @@ -490,6 +504,7 @@ def run_cli( override_cli_path=override_cli_path, override_pre_args=override_pre_args, override_post_args=override_post_args, + sudo=sudo, ) # Prepare the full list of CLI arguments. diff --git a/meta_package_manager/managers/apt.py b/meta_package_manager/managers/apt.py index 4301c353e..fc981088e 100644 --- a/meta_package_manager/managers/apt.py +++ b/meta_package_manager/managers/apt.py @@ -223,7 +223,7 @@ def install(self, package_id): ► sudo apt install git --yes --quiet """ super().install(package_id) - return self.run_cli("install", package_id, override_pre_cmds=("sudo",)) + return self.run_cli("install", package_id, sudo=True) def upgrade_cli(self, package_id=None): """Generates the CLI to upgrade all packages (default) or only the one provided as parameter. @@ -237,10 +237,8 @@ def upgrade_cli(self, package_id=None): ► sudo apt install --only-upgrade git --yes --quiet """ if package_id: - return self.build_cli( - "install", "--only-upgrade", package_id, override_pre_cmds=("sudo",) - ) - return self.build_cli("upgrade", override_pre_cmds=("sudo",)) + return self.build_cli("install", "--only-upgrade", package_id, sudo=True) + return self.build_cli("upgrade", sudo=True) def sync(self): """Sync package metadata. @@ -258,7 +256,7 @@ def sync(self): Reading state information... """ super().sync() - self.run_cli("update", override_pre_cmds=("sudo",)) + self.run_cli("update", sudo=True) def cleanup(self): """Removes things we don't need anymore. @@ -270,7 +268,7 @@ def cleanup(self): """ super().cleanup() for command in ("autoremove", "clean"): - self.run_cli(command, override_pre_cmds=("sudo",)) + self.run_cli(command, sudo=True) class APT_Mint(APT): diff --git a/meta_package_manager/managers/dnf.py b/meta_package_manager/managers/dnf.py index abb600ddf..21747266f 100644 --- a/meta_package_manager/managers/dnf.py +++ b/meta_package_manager/managers/dnf.py @@ -166,9 +166,7 @@ def install(self, package_id): ► sudo dnf --color=never --assumeyes install pip """ super().install(package_id) - return self.run_cli( - "--assumeyes", "install", package_id, override_pre_cmds=("sudo",) - ) + return self.run_cli("--assumeyes", "install", package_id, sudo=True) def upgrade_cli(self, package_id=None): """Generates the CLI to upgrade all packages (default) or only the one provided as parameter. @@ -181,7 +179,7 @@ def upgrade_cli(self, package_id=None): ► sudo dnf --color=never --assumeyes upgrade pip """ - return self.build_cli("upgrade", package_id) + return self.build_cli("upgrade", package_id, sudo=True) def sync(self): """Sync package metadata. @@ -202,5 +200,5 @@ def cleanup(self): ► dnf --color=never clean all """ super().cleanup() - self.run_cli("--assumeyes", "autoremove", override_pre_cmds=("sudo",)) + self.run_cli("--assumeyes", "autoremove", sudo=True) self.run_cli("clean", "all") diff --git a/meta_package_manager/managers/emerge.py b/meta_package_manager/managers/emerge.py index a1e03aa65..d9627e7fd 100644 --- a/meta_package_manager/managers/emerge.py +++ b/meta_package_manager/managers/emerge.py @@ -216,7 +216,7 @@ def install(self, package_id): ► sudo emerge --color n --nospinner dev-vcs/git """ super().install(package_id) - return self.run_cli("--color", "n", "--nospinner", package_id, override_pre_cmds=("sudo",)) + return self.run_cli("--color", "n", "--nospinner", package_id, sudo=True) def upgrade_cli(self, package_id="@world"): """Generates the CLI to upgrade all packages (default) or only the one provided as parameter. @@ -233,7 +233,7 @@ def upgrade_cli(self, package_id="@world"): if package_id == "@world": update_params = ("--newuse", "--deep") - return self.build_cli("--update", *update_params, "--color", "n", "--nospinner", package_id, override_pre_cmds=("sudo",)) + return self.build_cli("--update", *update_params, "--color", "n", "--nospinner", package_id, sudo=True) def sync(self): """Sync package metadata. @@ -243,7 +243,7 @@ def sync(self): ► sudo emerge --sync --color n --nospinner """ super().sync() - self.run_cli("--sync", "--color", "n", "--nospinner", override_pre_cmds=("sudo",)) + self.run_cli("--sync", "--color", "n", "--nospinner", sudo=True) def cleanup(self): """Removes things we don't need anymore. @@ -263,5 +263,6 @@ def cleanup(self): super().cleanup() # Forces an upgrade first, as recommended by emerge documentation. self.upgrade() - self.run_cli("--depclean", override_pre_cmds=("sudo",)) - self.run_cli("distfiles", override_cli_path="eclean", override_pre_cmds=("sudo",)) + self.run_cli("--depclean", sudo=True) + # XXX + self.run_cli("distfiles", override_cli_path="eclean", sudo=True)