From e3774822abcfd5be655cf7459c518beb3dc82b90 Mon Sep 17 00:00:00 2001
From: "Owen W. Taylor" <otaylor@fishsoup.net>
Date: Fri, 22 Oct 2021 14:20:56 -0400
Subject: [PATCH] dnf: Update appstream xml files if dnf_sack_add_repos() does
the download
We were copying appstream xml files into /var/cache/app-info/xmls when we did
the repository download directly by calling dnf_repo_update(), but
dnf_repo_update() can also be implicitly called by dnf_sack_add_repos().
Check before calling dnf_sack_add_repos() which repos look out-of-date
and copy over their appstream info afterwards.
---
backends/dnf/pk-backend-dnf.c | 134 ++++++++++++++++++++++------------
1 file changed, 89 insertions(+), 45 deletions(-)
diff --git a/backends/dnf/pk-backend-dnf.c b/backends/dnf/pk-backend-dnf.c
index e62f40ff4..42ae19602 100644
--- a/backends/dnf/pk-backend-dnf.c
+++ b/backends/dnf/pk-backend-dnf.c
@@ -70,6 +70,12 @@ typedef struct {
HyGoal goal;
} PkBackendDnfJobData;
+static GPtrArray * pk_backend_find_refresh_repos (PkBackendJob *job,
+ DnfState *state,
+ GPtrArray *repos,
+ gboolean force,
+ GError **error);
+
const gchar *
pk_backend_get_description (PkBackend *backend)
{
@@ -555,11 +561,13 @@ dnf_utils_add_remote (PkBackendJob *job,
gboolean ret;
DnfState *state_local;
g_autoptr(GPtrArray) repos = NULL;
+ g_autoptr(GPtrArray) refresh_repos = NULL;
/* set state */
ret = dnf_state_set_steps (state, error,
2, /* load files */
- 98, /* add repos */
+ 1, /* count */
+ 97, /* add repos */
-1);
if (!ret)
return FALSE;
@@ -573,6 +581,20 @@ dnf_utils_add_remote (PkBackendJob *job,
if (!dnf_state_done (state, error))
return FALSE;
+ /* Find out what repositories potentially will get downloaded - we might need to update
+ * the appstream data for these repositories. Note that there is a small chance that the
+ * repo metadata could expire between the call to dnf_repo_check() at this point, and
+ * the call to dnf_repo_check() inside dnf_sack_add_repos() - in this case we'll end up
+ * with stale appstream data until the next metadata refresh.
+ */
+ refresh_repos = pk_backend_find_refresh_repos (job,
+ state,
+ repos,
+ FALSE /* !force */,
+ error);
+ if (refresh_repos == NULL)
+ return FALSE;
+
/* add each repo */
state_local = dnf_state_get_child (state);
ret = dnf_sack_add_repos (sack,
@@ -584,6 +606,12 @@ dnf_utils_add_remote (PkBackendJob *job,
if (!ret)
return FALSE;
+ for (guint i = 0; i < refresh_repos->len; i++) {
+ DnfRepo *repo = g_ptr_array_index (refresh_repos, i);
+ if (!dnf_utils_refresh_repo_appstream (repo, error))
+ return FALSE;
+ }
+
/* done */
if (!dnf_state_done (state, error))
return FALSE;
@@ -1655,49 +1683,22 @@ pk_backend_refresh_subman (PkBackendJob *job)
pk_backend_repo_list_changed (backend);
}
-static void
-pk_backend_refresh_cache_thread (PkBackendJob *job,
- GVariant *params,
- gpointer user_data)
+static GPtrArray *
+pk_backend_find_refresh_repos (PkBackendJob *job,
+ DnfState *state,
+ GPtrArray *repos,
+ gboolean force,
+ GError **error)
{
- PkBackendDnfJobData *job_data = pk_backend_job_get_user_data (job);
- PkBackend *backend = pk_backend_job_get_backend (job);
- DnfRepo *repo;
+ g_autoptr(GPtrArray) refresh_repos = NULL;
DnfState *state_local;
DnfState *state_loop;
- gboolean force;
- gboolean ret;
guint cnt = 0;
guint i;
- g_autoptr(DnfSack) sack = NULL;
- g_autoptr(GError) error = NULL;
- g_autoptr(GPtrArray) refresh_repos = NULL;
- g_autoptr(GPtrArray) repos = NULL;
-
- /* set state */
- dnf_state_set_steps (job_data->state, NULL,
- 1, /* count */
- 95, /* download */
- 4, /* rebuild SAT */
- -1);
-
- g_variant_get (params, "(b)", &force);
-
- /* kick subscription-manager if it exists */
- pk_backend_refresh_subman (job);
-
- /* ask the context's repo loader for new repos, forcing it to reload them */
- repos = dnf_repo_loader_get_repos (dnf_context_get_repo_loader (job_data->context), &error);
- if (repos == NULL) {
- pk_backend_job_error_code (job,
- error->code,
- "failed to load repos: %s", error->message);
- return;
- }
/* count the enabled repos */
for (i = 0; i < repos->len; i++) {
- repo = g_ptr_array_index (repos, i);
+ DnfRepo *repo = g_ptr_array_index (repos, i);
if (dnf_repo_get_enabled (repo) == DNF_REPO_ENABLED_NONE)
continue;
if (dnf_repo_get_kind (repo) == DNF_REPO_KIND_MEDIA)
@@ -1709,12 +1710,12 @@ pk_backend_refresh_cache_thread (PkBackendJob *job,
/* figure out which repos need refreshing */
refresh_repos = g_ptr_array_new ();
- state_local = dnf_state_get_child (job_data->state);
+ state_local = dnf_state_get_child (state);
dnf_state_set_number_steps (state_local, cnt);
for (i = 0; i < repos->len; i++) {
+ DnfRepo *repo = g_ptr_array_index (repos, i);
gboolean repo_okay;
- repo = g_ptr_array_index (repos, i);
if (dnf_repo_get_enabled (repo) == DNF_REPO_ENABLED_NONE)
continue;
if (dnf_repo_get_kind (repo) == DNF_REPO_KIND_MEDIA)
@@ -1733,16 +1734,59 @@ pk_backend_refresh_cache_thread (PkBackendJob *job,
g_ptr_array_index (repos, i));
/* done */
- ret = dnf_state_done (state_local, &error);
- if (!ret) {
- pk_backend_job_error_code (job, error->code, "%s", error->message);
- return;
- }
+ if (!dnf_state_done (state_local, error))
+ return NULL;
}
/* done */
- ret = dnf_state_done (job_data->state, &error);
- if (!ret) {
+ if (!dnf_state_done (state, error))
+ return NULL;
+
+ return g_steal_pointer (&refresh_repos);
+}
+
+static void
+pk_backend_refresh_cache_thread (PkBackendJob *job,
+ GVariant *params,
+ gpointer user_data)
+{
+ PkBackendDnfJobData *job_data = pk_backend_job_get_user_data (job);
+ PkBackend *backend = pk_backend_job_get_backend (job);
+ DnfRepo *repo;
+ DnfState *state_local;
+ DnfState *state_loop;
+ gboolean force;
+ gboolean ret;
+ guint i;
+ g_autoptr(DnfSack) sack = NULL;
+ g_autoptr(GError) error = NULL;
+ g_autoptr(GPtrArray) refresh_repos = NULL;
+ g_autoptr(GPtrArray) repos = NULL;
+
+ /* set state */
+ dnf_state_set_steps (job_data->state, NULL,
+ 1, /* count */
+ 95, /* download */
+ 4, /* rebuild SAT */
+ -1);
+
+ g_variant_get (params, "(b)", &force);
+
+ /* kick subscription-manager if it exists */
+ pk_backend_refresh_subman (job);
+
+ /* ask the context's repo loader for new repos, forcing it to reload them */
+ repos = dnf_repo_loader_get_repos (dnf_context_get_repo_loader (job_data->context), &error);
+ if (repos == NULL) {
+ pk_backend_job_error_code (job,
+ error->code,
+ "failed to load repos: %s", error->message);
+ return;
+ }
+
+ /* figure out which repos need refreshing */
+ refresh_repos = pk_backend_find_refresh_repos (job, job_data->state, repos, force, &error);
+ if (refresh_repos == NULL) {
pk_backend_job_error_code (job, error->code, "%s", error->message);
return;
}
--
2.29.2