mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-04-22 10:01:45 +00:00
package: Introduce component API for package conflicts
This is help in eliminating the module level package_conflicts declarations. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
1681aeb2f9
commit
82876a6e23
@ -3,12 +3,13 @@
|
||||
Framework for installing and updating distribution packages
|
||||
"""
|
||||
|
||||
import enum
|
||||
import json
|
||||
import logging
|
||||
import subprocess
|
||||
import sys
|
||||
import threading
|
||||
from typing import Union
|
||||
from typing import Optional, Union
|
||||
|
||||
import apt.cache
|
||||
from django.utils.translation import gettext as _
|
||||
@ -28,8 +29,15 @@ class Packages(app.FollowerComponent):
|
||||
of packages required by an app.
|
||||
"""
|
||||
|
||||
class ConflictsAction(enum.Enum):
|
||||
"""Action to take when a conflicting package is installed."""
|
||||
IGNORE = 'ignore' # Proceed as if there are no conflicts
|
||||
REMOVE = 'remove' # Remove the packages before installing the app
|
||||
|
||||
def __init__(self, component_id: str, packages: list[str],
|
||||
skip_recommends=False):
|
||||
skip_recommends: bool = False,
|
||||
conflicts: Optional[list[str]] = None,
|
||||
conflicts_action: Optional[ConflictsAction] = None):
|
||||
"""Initialize a new packages component.
|
||||
|
||||
'component_id' should be a unique ID across all components of an app
|
||||
@ -39,12 +47,22 @@ class Packages(app.FollowerComponent):
|
||||
|
||||
'skip_recommends' is a boolean specifying whether recommended packages
|
||||
should be installed along with the listed packages.
|
||||
|
||||
'conflicts' is the list of Debian packages that can't simultaneously be
|
||||
installed with packages listed here. None if there are no known
|
||||
conflicting packages.
|
||||
|
||||
'conflicts_action' is a string representing the action to take when it
|
||||
is found that conflicting Debian packages are installed on the system.
|
||||
None if there are no known conflicting packages.
|
||||
"""
|
||||
super().__init__(component_id)
|
||||
|
||||
self.component_id = component_id
|
||||
self._packages = packages
|
||||
self.skip_recommends = skip_recommends
|
||||
self.conflicts = conflicts
|
||||
self.conflicts_action = conflicts_action
|
||||
|
||||
@property
|
||||
def packages(self) -> list[str]:
|
||||
@ -59,6 +77,13 @@ class Packages(app.FollowerComponent):
|
||||
helper = module.setup_helper
|
||||
helper.install(self.packages, skip_recommends=self.skip_recommends)
|
||||
|
||||
def find_conflicts(self) -> Optional[list[str]]:
|
||||
"""Return list of conflicting packages installed on the system."""
|
||||
if not self.conflicts:
|
||||
return None
|
||||
|
||||
return packages_installed(self.conflicts)
|
||||
|
||||
|
||||
class PackageException(Exception):
|
||||
"""A package operation has failed."""
|
||||
|
||||
@ -20,13 +20,19 @@ def test_packages_init():
|
||||
assert component.component_id == 'test-component'
|
||||
assert component.packages == ['foo', 'bar']
|
||||
assert not component.skip_recommends
|
||||
assert component.conflicts is None
|
||||
assert component.conflicts_action is None
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
Packages(None, [])
|
||||
|
||||
component = Packages('test-component', [], skip_recommends=True)
|
||||
component = Packages('test-component', [], skip_recommends=True,
|
||||
conflicts=['conflict1', 'conflict2'],
|
||||
conflicts_action=Packages.ConflictsAction.IGNORE)
|
||||
assert component.packages == []
|
||||
assert component.skip_recommends
|
||||
assert component.conflicts == ['conflict1', 'conflict2']
|
||||
assert component.conflicts_action == Packages.ConflictsAction.IGNORE
|
||||
|
||||
|
||||
def test_packages_setup():
|
||||
@ -54,6 +60,26 @@ def test_packages_setup():
|
||||
[call(['foo2', 'bar2'], skip_recommends=True)])
|
||||
|
||||
|
||||
@patch('plinth.package.packages_installed')
|
||||
def test_packages_find_conflicts(packages_installed_):
|
||||
"""Test finding conflicts."""
|
||||
packages_installed_.return_value = []
|
||||
component = Packages('test-component', ['package3', 'package4'])
|
||||
assert component.find_conflicts() is None
|
||||
|
||||
packages_installed_.return_value = []
|
||||
component = Packages('test-component', ['package3', 'package4'],
|
||||
conflicts=['package5', 'package6'],
|
||||
conflicts_action=Packages.ConflictsAction.IGNORE)
|
||||
assert component.find_conflicts() == []
|
||||
|
||||
packages_installed_.return_value = ['package1', 'package2']
|
||||
component = Packages('test-component', ['package3', 'package4'],
|
||||
conflicts=['package1', 'package2'],
|
||||
conflicts_action=Packages.ConflictsAction.IGNORE)
|
||||
assert component.find_conflicts() == ['package1', 'package2']
|
||||
|
||||
|
||||
def test_packages_installed():
|
||||
"""Test packages_installed()."""
|
||||
# list as input
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user