mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-08-26 12:46:08 +00:00
package: Add functions for removing packages
Functions needed to spot and remove installed conflicting packages before installation of apps. - Remove all packages in a single operation as this way apt can search for solutions to conflicts more easily. - Use type hints rather than a lot of type checking. Type hints shall later be enforced using offline checking (with mypy) or at runtime (with enforce, etc.). Signed-off-by: Fioddor Superconcentrado <fioddor@gmail.com> [sunil: Run single remove operation on all packages] [sunil: Use type hints instead of extensive type checking] [sunil: Trim down the test case as it would only succeed after install] Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org> package
This commit is contained in:
parent
cb539cf1e8
commit
24f7ffe3cf
@ -48,6 +48,11 @@ def parse_arguments():
|
|||||||
'module', help='name of module for which package is being installed')
|
'module', help='name of module for which package is being installed')
|
||||||
subparser.add_argument('packages', nargs='+',
|
subparser.add_argument('packages', nargs='+',
|
||||||
help='list of packages to install')
|
help='list of packages to install')
|
||||||
|
|
||||||
|
subparser = subparsers.add_parser('remove', help='remove the package(s)')
|
||||||
|
subparser.add_argument('--packages', required=True,
|
||||||
|
help='List of packages to remove', nargs='+')
|
||||||
|
|
||||||
subparsers.add_parser('is-package-manager-busy',
|
subparsers.add_parser('is-package-manager-busy',
|
||||||
help='Return whether package manager is busy')
|
help='Return whether package manager is busy')
|
||||||
subparser = subparsers.add_parser(
|
subparser = subparsers.add_parser(
|
||||||
@ -100,6 +105,11 @@ def subcommand_install(arguments):
|
|||||||
sys.exit(returncode)
|
sys.exit(returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_remove(arguments):
|
||||||
|
"""Remove apt package(s)."""
|
||||||
|
sys.exit(run_apt_command(['remove'] + arguments.packages))
|
||||||
|
|
||||||
|
|
||||||
def _assert_managed_packages(module, packages):
|
def _assert_managed_packages(module, packages):
|
||||||
"""Check that list of packages are in fact managed by module."""
|
"""Check that list of packages are in fact managed by module."""
|
||||||
cfg.read()
|
cfg.read()
|
||||||
@ -116,7 +126,8 @@ def _assert_managed_packages(module, packages):
|
|||||||
def subcommand_is_package_manager_busy(_):
|
def subcommand_is_package_manager_busy(_):
|
||||||
"""Check whether package manager is busy.
|
"""Check whether package manager is busy.
|
||||||
|
|
||||||
An exit code of zero indicates that package manager is busy."""
|
An exit code of zero indicates that package manager is busy.
|
||||||
|
"""
|
||||||
if not is_package_manager_busy():
|
if not is_package_manager_busy():
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|||||||
@ -7,11 +7,14 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import apt.cache
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
from django.utils.translation import gettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
|
|
||||||
from plinth import actions
|
from plinth import actions
|
||||||
|
from plinth.errors import ActionError, PlinthError
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -195,3 +198,30 @@ def filter_conffile_prompt_packages(packages):
|
|||||||
'packages',
|
'packages',
|
||||||
['filter-conffile-packages', '--packages'] + list(packages))
|
['filter-conffile-packages', '--packages'] + list(packages))
|
||||||
return json.loads(response)
|
return json.loads(response)
|
||||||
|
|
||||||
|
|
||||||
|
def packages_installed(candidates: Union[list, tuple]) -> list:
|
||||||
|
"""Check which candidates are installed on the system.
|
||||||
|
|
||||||
|
:param candidates: A list of package names.
|
||||||
|
:return: A list of installed Debian package names.
|
||||||
|
"""
|
||||||
|
cache = apt.cache.Cache()
|
||||||
|
installed_packages = []
|
||||||
|
for package_name in candidates:
|
||||||
|
try:
|
||||||
|
package = cache[package_name]
|
||||||
|
if package.is_installed:
|
||||||
|
installed_packages.append(package_name)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return installed_packages
|
||||||
|
|
||||||
|
|
||||||
|
def remove(packages: Union[list, tuple]) -> None:
|
||||||
|
"""Remove packages."""
|
||||||
|
try:
|
||||||
|
actions.superuser_run('packages', ['remove', '--packages'] + packages)
|
||||||
|
except ActionError:
|
||||||
|
pass
|
||||||
|
|||||||
35
plinth/tests/test_package.py
Normal file
35
plinth/tests/test_package.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
"""
|
||||||
|
Test module for package module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from unittest.mock import call, patch
|
||||||
|
|
||||||
|
from plinth.errors import ActionError
|
||||||
|
from plinth.package import packages_installed, remove
|
||||||
|
|
||||||
|
|
||||||
|
def test_packages_installed():
|
||||||
|
"""Test packages_installed()."""
|
||||||
|
# list as input
|
||||||
|
assert len(packages_installed([])) == 0
|
||||||
|
assert len(packages_installed(['unknown-package'])) == 0
|
||||||
|
assert len(packages_installed(['python3'])) == 1
|
||||||
|
# tuples as input
|
||||||
|
assert len(packages_installed(())) == 0
|
||||||
|
assert len(packages_installed(('unknown-package', ))) == 0
|
||||||
|
assert len(packages_installed(('python3', ))) == 1
|
||||||
|
|
||||||
|
|
||||||
|
@patch('plinth.actions.superuser_run')
|
||||||
|
def test_remove(run):
|
||||||
|
"""Test removing packages."""
|
||||||
|
remove(['package1', 'package2'])
|
||||||
|
run.assert_has_calls(
|
||||||
|
[call('packages', ['remove', '--packages', 'package1', 'package2'])])
|
||||||
|
|
||||||
|
run.reset_mock()
|
||||||
|
run.side_effect = ActionError()
|
||||||
|
remove(['package1'])
|
||||||
|
run.assert_has_calls(
|
||||||
|
[call('packages', ['remove', '--packages', 'package1'])])
|
||||||
Loading…
x
Reference in New Issue
Block a user