From acd2f515d7607e7e136cf987bf3e9a5c1f891912 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Wed, 30 Jul 2025 21:13:32 -0700 Subject: [PATCH] package: Refresh apt cache if old and some packages are not found Fixes: #1358 - Refresh the apt cache if required packages for an app are not found and if the cache is more than 1 hour old (or non-existent). - If required packages are found, don't refresh the package cache even if the cache is outdated. This is because the check operation could lead to many minutes of waiting before app can be installed. Tests: - Remove /var/lib/apt/lists/* and /var/cache/apt/pkgcache.bin. Visit an app setup page. apt cache is updated and it take a while to check that the app is available. App is shown as available. If page is refreshed, this time, the cache is not updated. - Set the modification of /var/cache/apt/pkgcache.bin file to more than 2 hours ago with 'touch -d "2 hours ago" /var/cache/apt/pkgcache.bin'. Then refreshing the page will not refresh the cache. - Repeat test with an app that is not available such as Janus. Again apt cache is refreshed. App is shown as not available. On refresh, the cache is not updated. - Set the modification of /var/cache/apt/pkgcache.bin file to more than 2 hours ago with 'touch -d "2 hours ago" /var/cache/apt/pkgcache.bin'. Then refreshing the page will not refresh the cache. Signed-off-by: Sunil Mohan Adapa Reviewed-by: Joseph Nuthalapati - Remove redundant if condition in setup.html template - Use JavaScript fetch() API instead of XMLHTTPRequest class - Update a comment in test_package.py Signed-off-by: Joseph Nuthalapati --- plinth/package.py | 26 ++++++++++++----- plinth/templates/setup.html | 3 +- plinth/tests/test_package.py | 34 ++++++++++++++++++---- static/themes/default/js/main.js | 49 +++++++++++++------------------- 4 files changed, 68 insertions(+), 44 deletions(-) diff --git a/plinth/package.py b/plinth/package.py index e4cfcf551..0550cfe7c 100644 --- a/plinth/package.py +++ b/plinth/package.py @@ -255,14 +255,26 @@ class Packages(app_module.FollowerComponent): Returns True if all of the packages are available in the user's Debian distribution or False otherwise. Returns True 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 True # Don't know, package cache is not available - # List of all packages from all Package components + This operation can run for a long time as package cache may be + refreshed. + """ + try: + self.get_actual_packages() + return True # All packages were found in the cache + except MissingPackageError: + pass # We will retry after refreshing package list + + # If the package cache is new, then package is really not available. + package_cache = pathlib.Path('/var/cache/apt/pkgcache.bin') + if (package_cache.exists() + and time.time() - package_cache.stat().st_mtime < 3600): + return False + + # Perform 'apt-get update' + refresh_package_lists() + + # Check again for all the packages try: self.get_actual_packages() except MissingPackageError: diff --git a/plinth/templates/setup.html b/plinth/templates/setup.html index cbf6e316f..4523f7d7b 100644 --- a/plinth/templates/setup.html +++ b/plinth/templates/setup.html @@ -62,8 +62,7 @@
{% csrf_token %} - {% if has_unavailable_packages %} - {% elif package_conflicts and package_conflicts_action.value != 'ignore' %} + {% if package_conflicts and package_conflicts_action.value != 'ignore' %}