packages: Move checking for unavailable packages to component

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2021-11-18 09:43:56 -08:00 committed by James Valleroy
parent fb40bb7f42
commit 929e7f6dba
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
5 changed files with 51 additions and 31 deletions

View File

@ -6,6 +6,7 @@ Framework for installing and updating distribution packages
import enum
import json
import logging
import pathlib
import subprocess
import sys
import threading
@ -84,6 +85,25 @@ class Packages(app.FollowerComponent):
return packages_installed(self.conflicts)
def has_unavailable_packages(self):
"""Return whether any of the packages are not available.
Returns True if one or more of the packages is not available in the
user's Debian distribution or False otherwise. Returns None if it
cannot be reliably determined whether the packages are available or
not.
"""
apt_lists_dir = pathlib.Path('/var/lib/apt/lists/')
num_files = len(
[child for child in apt_lists_dir.iterdir() if child.is_file()])
if num_files < 2: # not counting the lock file
return None
# List of all packages from all Package components
cache = apt.Cache()
return any(package for package in self.packages
if package not in cache)
class PackageException(Exception):
"""A package operation has failed."""

View File

@ -5,7 +5,6 @@ Utilities for performing application setup operations.
import importlib
import logging
import os
import threading
import time
from collections import defaultdict
@ -159,34 +158,6 @@ class Helper(object):
models.Module.objects.update_or_create(
pk=self.module_name, defaults={'setup_version': version})
def has_unavailable_packages(self):
"""Find if any of the packages managed by the module are not available.
Returns True if one or more of the packages is not available in the
user's Debian distribution or False otherwise.
Returns None if it cannot be reliably determined whether the
packages are available or not.
"""
APT_LISTS_DIR = '/var/lib/apt/lists/'
num_files = len([
name for name in os.listdir(APT_LISTS_DIR)
if os.path.isfile(os.path.join(APT_LISTS_DIR, name))
])
if num_files < 2: # not counting the lock file
return None
pkg_components = list(self.module.app.get_components_of_type(Packages))
if not pkg_components: # This app has no packages to install
return False
# List of all packages from all Package components
managed_pkgs = (package for component in pkg_components
for package in component.packages)
cache = apt.Cache()
unavailable_pkgs = (pkg_name for pkg_name in managed_pkgs
if pkg_name not in cache)
return any(unavailable_pkgs)
def init(module_name, module):
"""Create a setup helper for a module for later use."""

View File

@ -41,7 +41,7 @@
Please wait for a few moments before trying again.
{% endblocktrans %}
</div>
{% elif setup_helper.has_unavailable_packages %}
{% elif has_unavailable_packages %}
<div class="alert alert-warning" role="alert">
{% blocktrans trimmed %}
This application is currently not available in your distribution.
@ -64,7 +64,7 @@
{% endif %}
<input type="submit" class="btn btn-md btn-primary" name="install"
{% if package_manager_is_busy or setup_helper.has_unavailable_packages %}
{% if package_manager_is_busy or has_unavailable_packages %}
disabled="disabled"
{% endif %}
{% if setup_state == 'needs-setup' %}

View File

@ -80,6 +80,25 @@ def test_packages_find_conflicts(packages_installed_):
assert component.find_conflicts() == ['package1', 'package2']
@patch('apt.Cache')
@patch('pathlib.Path')
def test_packages_has_unavailable_packages(path_class, cache):
"""Test checking for unavailable packages."""
path = Mock()
path_class.return_value = path
path.iterdir.return_value = [Mock()]
component = Packages('test-component', ['package1', 'package2'])
assert component.has_unavailable_packages() is None
path.iterdir.return_value = [Mock(), Mock()]
cache.return_value = ['package1', 'package2']
assert not component.has_unavailable_packages()
cache.return_value = ['package1']
assert component.has_unavailable_packages()
def test_packages_installed():
"""Test packages_installed()."""
# list as input

View File

@ -288,6 +288,9 @@ class SetupView(TemplateView):
if not context['setup_current_operation']:
context[
'package_manager_is_busy'] = package.is_package_manager_busy()
context[
'has_unavailable_packages'] = self._has_unavailable_packages(
setup_helper.module.app)
context['refresh_page_sec'] = None
if context['setup_state'] == 'up-to-date':
@ -335,6 +338,13 @@ class SetupView(TemplateView):
return conflicts, conflicts_action
@staticmethod
def _has_unavailable_packages(app_):
"""Return whether the app has unavailable packages."""
components = app_.get_components_of_type(Packages)
return any(component for component in components
if component.has_unavailable_packages())
def notification_dismiss(request, id):
"""Dismiss a notification."""