[gnome-software] flatpak: Fix searching for installed bundles
- From: Richard Hughes <rhughes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software] flatpak: Fix searching for installed bundles
- Date: Fri, 12 Jun 2020 15:03:18 +0000 (UTC)
commit d306a601b2e0e39e8cc5391bdf22614020facf20
Author: Matthew Leeds <matthew leeds endlessm com>
Date: Wed Jan 22 19:18:54 2020 -0800
flatpak: Fix searching for installed bundles
This commit makes it so that when you search for a flatpak which was
installed from a bundle, it is returned as a result. The fix is twofold:
1. Save the XbSilo object which contains the appstream data from
flatpak_installed_ref_load_appdata() in a hash table and use it in
gs_flatpak_search().
2. Set the origin field in the appstream XML to the remote associated
with the flatpak (whereas currently it's set to "flatpak"). Otherwise
the app state will not be set by gs_flatpak_refine_app_state_unlocked()
since the origin doesn't match, and apps with unknown state are hidden
by gs_plugin_loader_app_is_valid().
plugins/flatpak/gs-flatpak.c | 104 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 87 insertions(+), 17 deletions(-)
---
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index 5b707b6d..01315e89 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -38,6 +38,8 @@ struct _GsFlatpak {
GRWLock silo_lock;
gchar *id;
guint changed_id;
+ GHashTable *app_silos;
+ GMutex app_silos_mutex;
};
G_DEFINE_TYPE (GsFlatpak, gs_flatpak, G_TYPE_OBJECT)
@@ -386,10 +388,10 @@ gs_flatpak_set_origin_cb (XbBuilderFixup *self,
gpointer user_data,
GError **error)
{
- FlatpakRemote *xremote = FLATPAK_REMOTE (user_data);
+ const char *remote_name = (char *)user_data;
if (g_strcmp0 (xb_builder_node_get_element (bn), "components") == 0) {
xb_builder_node_set_attr (bn, "origin",
- flatpak_remote_get_name (xremote));
+ remote_name);
}
return TRUE;
}
@@ -474,7 +476,8 @@ gs_flatpak_get_xremote_main_ref (GsFlatpak *self, FlatpakRemote *xremote, GError
#endif
static void
-fixup_flatpak_appstream_xml (XbBuilderSource *source)
+fixup_flatpak_appstream_xml (XbBuilderSource *source,
+ const char *origin)
{
g_autoptr(XbBuilderFixup) fixup1 = NULL;
g_autoptr(XbBuilderFixup) fixup2 = NULL;
@@ -500,6 +503,17 @@ fixup_flatpak_appstream_xml (XbBuilderSource *source)
NULL, NULL);
xb_builder_fixup_set_max_depth (fixup3, 2);
xb_builder_source_add_fixup (source, fixup3);
+
+ if (origin != NULL) {
+ g_autoptr(XbBuilderFixup) fixup4 = NULL;
+
+ /* override the *AppStream* origin */
+ fixup4 = xb_builder_fixup_new ("SetOrigin",
+ gs_flatpak_set_origin_cb,
+ g_strdup (origin), g_free);
+ xb_builder_fixup_set_max_depth (fixup4, 1);
+ xb_builder_source_add_fixup (source, fixup4);
+ }
}
static gboolean
@@ -516,7 +530,6 @@ gs_flatpak_add_apps_from_xremote (GsFlatpak *self,
g_autoptr(GFile) appstream_dir = NULL;
g_autoptr(GFile) file_xml = NULL;
g_autoptr(GSettings) settings = NULL;
- g_autoptr(XbBuilderFixup) origin_fixup = NULL;
g_autoptr(XbBuilderNode) info = NULL;
g_autoptr(XbBuilderSource) source = xb_builder_source_new ();
@@ -547,16 +560,7 @@ gs_flatpak_add_apps_from_xremote (GsFlatpak *self,
error))
return FALSE;
- fixup_flatpak_appstream_xml (source);
-
- /* override the *AppStream* origin */
- /* TODO: Make this fixup work for bundles so it can go in
- * fixup_flatpak_appstream_xml() */
- origin_fixup = xb_builder_fixup_new ("SetOrigin",
- gs_flatpak_set_origin_cb,
- xremote, NULL);
- xb_builder_fixup_set_max_depth (origin_fixup, 1);
- xb_builder_source_add_fixup (source, origin_fixup);
+ fixup_flatpak_appstream_xml (source, flatpak_remote_get_name (xremote));
/* add metadata */
icon_prefix = g_build_filename (appstream_dir_fn, "icons", NULL);
@@ -2240,6 +2244,7 @@ gs_flatpak_refine_appstream_release (XbNode *component, GsApp *app)
static gboolean
gs_flatpak_refine_appstream_from_bytes (GsFlatpak *self,
GsApp *app,
+ const char *origin, /* (nullable) */
GBytes *appstream_gz,
GsPluginRefineFlags flags,
GCancellable *cancellable,
@@ -2299,7 +2304,7 @@ gs_flatpak_refine_appstream_from_bytes (GsFlatpak *self,
xb_builder_fixup_set_max_depth (bundle_fixup, 2);
xb_builder_source_add_fixup (source, bundle_fixup);
- fixup_flatpak_appstream_xml (source);
+ fixup_flatpak_appstream_xml (source, origin);
xb_builder_import_source (builder, source);
silo = xb_builder_compile (builder,
@@ -2349,6 +2354,15 @@ gs_flatpak_refine_appstream_from_bytes (GsFlatpak *self,
/* use the default release as the version number */
gs_flatpak_refine_appstream_release (component_node, app);
+
+ /* save the silo so it can be used for searches */
+ {
+ g_autoptr(GMutexLocker) locker = g_mutex_locker_new (&self->app_silos_mutex);
+ g_hash_table_replace (self->app_silos,
+ gs_flatpak_app_get_ref_display (app),
+ g_steal_pointer (&silo));
+ }
+
return TRUE;
}
@@ -2400,7 +2414,12 @@ gs_flatpak_refine_appstream (GsFlatpak *self,
return TRUE;
g_debug ("using installed appdata for %s", gs_flatpak_app_get_ref_name (app));
- return gs_flatpak_refine_appstream_from_bytes (self, app, appstream_gz, flags, cancellable,
error);
+ return gs_flatpak_refine_appstream_from_bytes (self,
+ app,
+ flatpak_installed_ref_get_origin
(installed_ref),
+ appstream_gz,
+ flags,
+ cancellable, error);
}
if (!gs_appstream_refine_app (self->plugin, app, silo, component, flags, error))
@@ -2685,7 +2704,7 @@ gs_flatpak_file_to_app_bundle (GsFlatpak *self,
/* load AppStream */
appstream_gz = flatpak_bundle_ref_get_appstream (xref_bundle);
if (appstream_gz != NULL) {
- if (!gs_flatpak_refine_appstream_from_bytes (self, app, appstream_gz,
+ if (!gs_flatpak_refine_appstream_from_bytes (self, app, NULL, appstream_gz,
GS_PLUGIN_REFINE_FLAGS_DEFAULT,
cancellable, error))
return NULL;
@@ -2930,6 +2949,10 @@ gs_flatpak_search (GsFlatpak *self,
{
g_autoptr(GsAppList) list_tmp = gs_app_list_new ();
g_autoptr(GRWLockReaderLocker) locker = NULL;
+ g_autoptr(GMutexLocker) app_silo_locker = NULL;
+ g_autoptr(GPtrArray) silos_to_remove = g_ptr_array_new ();
+ GHashTableIter iter;
+ gpointer key, value;
if (!gs_flatpak_rescan_appstream_store (self, cancellable, error))
return FALSE;
@@ -2942,6 +2965,49 @@ gs_flatpak_search (GsFlatpak *self,
gs_flatpak_claim_app_list (self, list_tmp);
gs_app_list_add_list (list, list_tmp);
+ /* Also search silos from installed apps which were missing from self->silo */
+ app_silo_locker = g_mutex_locker_new (&self->app_silos_mutex);
+ g_hash_table_iter_init (&iter, self->app_silos);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_autoptr(XbSilo) app_silo = g_object_ref (value);
+ g_autoptr(GsAppList) app_list_tmp = gs_app_list_new ();
+ const char *app_ref = (char *)key;
+ g_autoptr(FlatpakInstalledRef) installed_ref = NULL;
+ g_auto(GStrv) split = NULL;
+ FlatpakRefKind kind;
+
+ /* Ignore any silos of apps that have since been removed.
+ * FIXME: can we use self->installed_refs here? */
+ split = g_strsplit (app_ref, "/", -1);
+ g_assert (g_strv_length (split) == 4);
+ if (g_strcmp0 (split[0], "app") == 0)
+ kind = FLATPAK_REF_KIND_APP;
+ else
+ kind = FLATPAK_REF_KIND_RUNTIME;
+ installed_ref = flatpak_installation_get_installed_ref (self->installation,
+ kind,
+ split[1],
+ split[2],
+ split[3],
+ NULL, NULL);
+ if (installed_ref == NULL) {
+ g_ptr_array_add (silos_to_remove, app_ref);
+ continue;
+ }
+
+ if (!gs_appstream_search (self->plugin, app_silo, values, app_list_tmp,
+ cancellable, error))
+ return FALSE;
+
+ gs_flatpak_claim_app_list (self, app_list_tmp);
+ gs_app_list_add_list (list, app_list_tmp);
+ }
+
+ for (guint i = 0; i < silos_to_remove->len; i++) {
+ const char *silo = g_ptr_array_index (silos_to_remove, i);
+ g_hash_table_remove (self->app_silos, silo);
+ }
+
return TRUE;
}
@@ -3118,6 +3184,8 @@ gs_flatpak_finalize (GObject *object)
g_hash_table_unref (self->broken_remotes);
g_mutex_clear (&self->broken_remotes_mutex);
g_rw_lock_clear (&self->silo_lock);
+ g_hash_table_unref (self->app_silos);
+ g_mutex_clear (&self->app_silos_mutex);
G_OBJECT_CLASS (gs_flatpak_parent_class)->finalize (object);
}
@@ -3141,6 +3209,8 @@ gs_flatpak_init (GsFlatpak *self)
g_mutex_init (&self->broken_remotes_mutex);
self->broken_remotes = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
+ self->app_silos = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ g_mutex_init (&self->app_silos_mutex);
}
GsFlatpak *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]