[gnome-software/wip/kalev/gnome-3-22: 80/96] Install flatpakref files in a better way



commit 4ea602d89c1a167fdeae0f026b4ec74a49672554
Author: Richard Hughes <richard hughsie com>
Date:   Wed Feb 22 10:14:22 2017 +0000

    Install flatpakref files in a better way
    
    At the moment we require the admin password to just view the details of a
    flatpakref file as we need to add the remote to fetch the AppStream data.
    This looks bad, and also leaves a noenumerate=true remote installed if the the
    user chooses not to install the application.
    
    To work around this, install the flatpakref into a temporary installation and
    download the AppStream information there, which will not need the system helper.
    When the user clicks install, then install the app into the chosen user/system
    location alon with its noenumerate=true remote for updates.
    
    To implement this, create an additional GsFlatpak object for this temporary
    installation. Care must be taken that we don't use this object for returning
    search results, and that we reset the 'chosen' GsFlatpak object ID to
    something other than the temporary installation when we actually come to
    install the application.
    
    (This commit cherry-picks the actual fixes from commit 4426454c on
    master without the associated self test changes.)

 src/plugins/gs-flatpak.c        |  109 ++++++++++++++++++++++++++++++++++++---
 src/plugins/gs-flatpak.h        |    1 +
 src/plugins/gs-plugin-flatpak.c |   55 ++++++++++++++++++++
 3 files changed, 158 insertions(+), 7 deletions(-)
---
diff --git a/src/plugins/gs-flatpak.c b/src/plugins/gs-flatpak.c
index 7a1bd6c..baba6b0 100644
--- a/src/plugins/gs-flatpak.c
+++ b/src/plugins/gs-flatpak.c
@@ -1457,11 +1457,11 @@ gs_plugin_refine_item_state (GsFlatpak *self,
                                gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
                        }
                } else {
-                       g_warning ("failed to find flatpak %s remote %s for %s",
-                                  flatpak_installation_get_is_user (self->installation) ? "user" : "system",
-                                  gs_app_get_origin (app),
-                                  gs_app_get_unique_id (app));
-                       g_warning ("%s", gs_app_to_string (app));
+                       gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
+                       g_debug ("failed to find %s remote %s for %s",
+                                self->id,
+                                gs_app_get_origin (app),
+                                gs_app_get_unique_id (app));
                }
        }
 
@@ -2049,6 +2049,9 @@ gs_flatpak_app_remove (GsFlatpak *self,
                       GCancellable *cancellable,
                       GError **error)
 {
+       g_autoptr(FlatpakRemote) xremote = NULL;
+       g_autofree gchar *remote_name = NULL;
+
        /* refine to get basics */
        if (!gs_flatpak_refine_app (self, app,
                                    GS_PLUGIN_REFINE_FLAGS_DEFAULT,
@@ -2076,6 +2079,23 @@ gs_flatpak_app_remove (GsFlatpak *self,
                return FALSE;
        }
 
+       /* did app also install a noenumerate=True remote */
+       remote_name = g_strdup_printf ("%s-origin", gs_app_get_flatpak_name (app));
+       xremote = flatpak_installation_get_remote_by_name (self->installation,
+                                                          remote_name,
+                                                          cancellable,
+                                                          NULL);
+       if (xremote != NULL) {
+               g_debug ("removing enumerate=true %s remote", remote_name);
+               if (!flatpak_installation_remove_remote (self->installation,
+                                                        remote_name,
+                                                        cancellable,
+                                                        error)) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+       }
+
        /* state is not known: we don't know if we can re-install this app */
        gs_app_set_state (app, AS_APP_STATE_UNKNOWN);
 
@@ -2181,7 +2201,8 @@ gs_flatpak_app_install (GsFlatpak *self,
        g_autoptr(FlatpakInstalledRef) xref = NULL;
 
        /* ensure we have metadata and state */
-       if (!gs_flatpak_refine_app (self, app, GS_PLUGIN_REFINE_FLAGS_DEFAULT,
+       if (!gs_flatpak_refine_app (self, app,
+                                   GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME,
                                    cancellable, error))
                return FALSE;
 
@@ -2196,6 +2217,39 @@ gs_flatpak_app_install (GsFlatpak *self,
                                                      error);
        }
 
+       /* flatpakref has to be done in two phases */
+       if (g_strcmp0 (gs_app_get_flatpak_file_type (app), "flatpakref") == 0) {
+               g_autoptr(FlatpakRemoteRef) xref2 = NULL;
+               gsize len = 0;
+               g_autofree gchar *contents = NULL;
+               g_autoptr(GBytes) data = NULL;
+               if (gs_app_get_local_file (app) == NULL) {
+                       g_set_error (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_NOT_SUPPORTED,
+                                    "no local file set for flatpakref %s",
+                                    gs_app_get_unique_id (app));
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+               g_debug ("installing flatpakref %s", gs_app_get_unique_id (app));
+               if (!g_file_load_contents (gs_app_get_local_file (app),
+                                          cancellable, &contents, &len,
+                                          NULL, error)) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+               data = g_bytes_new (contents, len);
+               xref2 = flatpak_installation_install_ref_file (self->installation,
+                                                             data,
+                                                             cancellable,
+                                                             error);
+               if (xref2 == NULL) {
+                       gs_app_set_state_recover (app);
+                       return FALSE;
+               }
+       }
+
        /* install required runtime if not already installed */
        if (gs_app_get_kind (app) == AS_APP_KIND_DESKTOP &&
            !install_runtime_for_app (self, app, cancellable, error)) {
@@ -2590,6 +2644,7 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
        g_autofree gchar *ref_homepage = NULL;
        g_autofree gchar *ref_icon = NULL;
        g_autofree gchar *ref_title = NULL;
+       g_autofree gchar *ref_name = NULL;
 
        /* get file data */
        if (!g_file_load_contents (file,
@@ -2619,6 +2674,39 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
                }
        }
 
+       /* get name */
+       ref_name = g_key_file_get_string (kf, "Flatpak Ref", "Name", error);
+       if (ref_name == NULL) {
+               return FALSE;
+       }
+
+       /* remove old version from the remote config */
+       if (self->flags & GS_FLATPAK_FLAG_IS_TEMPORARY) {
+               g_autofree gchar *remote_id_tmp = NULL;
+               g_autofree gchar *remote_name_tmp = NULL;
+               g_autoptr(FlatpakRemote) xremote_tmp = NULL;
+               remote_name_tmp = g_strdup_printf ("%s-origin", ref_name);
+               xremote_tmp = flatpak_installation_get_remote_by_name (self->installation,
+                                                                      remote_name_tmp,
+                                                                      cancellable,
+                                                                      NULL);
+               if (xremote_tmp != NULL) {
+                       g_debug ("removing previous remote %s", remote_name_tmp);
+                       if (!flatpak_installation_remove_remote (self->installation,
+                                                                remote_name_tmp,
+                                                                cancellable,
+                                                                error)) {
+                               return FALSE;
+                       }
+               } else {
+                       g_debug ("no previous %s remote to remove", remote_name_tmp);
+               }
+
+               /* remove from the store */
+               remote_id_tmp = g_strdup_printf ("%s.desktop", ref_name);
+               as_store_remove_app_by_id (self->store, remote_id_tmp);
+       }
+
        /* install the remote, but not the app */
        ref_file_data = g_bytes_new (contents, len);
        xref = flatpak_installation_install_ref_file (self->installation,
@@ -2687,6 +2775,10 @@ gs_flatpak_file_to_app_ref (GsFlatpak *self,
                return FALSE;
        }
 
+       /* get this now, as it's not going to be available at install time */
+       if (!gs_plugin_refine_item_metadata (self, app, cancellable, error))
+               return FALSE;
+
        /* parse it */
        if (!gs_flatpak_add_apps_from_xremote (self, xremote, cancellable, error))
                return FALSE;
@@ -2732,7 +2824,8 @@ gs_flatpak_file_to_app (GsFlatpak *self,
                                                    cancellable,
                                                    error);
        }
-       if (g_strv_contains (mimetypes_ref, content_type)) {
+       if (self->flags & GS_FLATPAK_FLAG_IS_TEMPORARY &&
+           g_strv_contains (mimetypes_ref, content_type)) {
                return gs_flatpak_file_to_app_ref (self,
                                                   list,
                                                   file,
@@ -2816,6 +2909,8 @@ gs_flatpak_get_id (GsFlatpak *self)
                GString *str = g_string_new ("GsFlatpak");
                g_string_append_printf (str, "-%s",
                                        as_app_scope_to_string (self->scope));
+               if (self->flags & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       g_string_append (str, "-temp");
                self->id = g_string_free (str, FALSE);
        }
        return self->id;
diff --git a/src/plugins/gs-flatpak.h b/src/plugins/gs-flatpak.h
index af80dfd..182434a 100644
--- a/src/plugins/gs-flatpak.h
+++ b/src/plugins/gs-flatpak.h
@@ -48,6 +48,7 @@ G_DECLARE_FINAL_TYPE (GsFlatpak, gs_flatpak, GS, FLATPAK, GObject)
 
 typedef enum {
        GS_FLATPAK_FLAG_NONE                    = 0,
+       GS_FLATPAK_FLAG_IS_TEMPORARY            = 1 << 0,
        /*< private >*/
        GS_FLATPAK_FLAG_LAST
 } GsFlatpakFlags;
diff --git a/src/plugins/gs-plugin-flatpak.c b/src/plugins/gs-plugin-flatpak.c
index 158db83..afa9004 100644
--- a/src/plugins/gs-plugin-flatpak.c
+++ b/src/plugins/gs-plugin-flatpak.c
@@ -183,6 +183,32 @@ gs_plugin_setup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
                }
        }
 
+       /* add temporary installation for flatpakref files */
+       if (TRUE) {
+               g_autofree gchar *installation_path = NULL;
+               g_autoptr(FlatpakInstallation) installation = NULL;
+               g_autoptr(GFile) installation_file = NULL;
+               installation_path = gs_utils_get_cache_filename ("flatpak",
+                                                                "installation-tmp",
+                                                                GS_UTILS_CACHE_FLAG_WRITEABLE,
+                                                                error);
+               if (installation_path == NULL)
+                       return FALSE;
+               installation_file = g_file_new_for_path (installation_path);
+               installation = flatpak_installation_new_for_path (installation_file,
+                                                                 TRUE, /* user */
+                                                                 cancellable,
+                                                                 error);
+               if (installation == NULL) {
+                       return FALSE;
+               }
+               if (!gs_plugin_flatpak_add_installation (plugin, installation,
+                                                        GS_FLATPAK_FLAG_IS_TEMPORARY,
+                                                        cancellable, error)) {
+                       return FALSE;
+               }
+       }
+
        return TRUE;
 }
 
@@ -195,6 +221,8 @@ gs_plugin_add_installed (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_installed (flatpak, list, cancellable, error))
                        return FALSE;
        }
@@ -210,6 +238,8 @@ gs_plugin_add_sources (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_sources (flatpak, list, cancellable, error))
                        return FALSE;
        }
@@ -225,6 +255,8 @@ gs_plugin_add_updates (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_updates (flatpak, list, cancellable, error))
                        return FALSE;
        }
@@ -241,6 +273,8 @@ gs_plugin_refresh (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_refresh (flatpak, cache_age, flags,
                                         cancellable, error)) {
                        return FALSE;
@@ -310,6 +344,8 @@ gs_plugin_refine_wildcard (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_refine_wildcard (flatpak, app, list, flags,
                                                 cancellable, error)) {
                        return FALSE;
@@ -351,6 +387,17 @@ gs_plugin_app_install (GsPlugin *plugin,
        GsFlatpak *flatpak = gs_plugin_flatpak_get_handler (plugin, app);
        if (flatpak == NULL)
                return TRUE;
+
+       /* reset the temporary GsFlatpak object ID */
+       if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY) {
+               g_debug ("resetting temporary object ID");
+               gs_app_set_flatpak_object_id (app, NULL);
+               flatpak = gs_plugin_flatpak_get_handler (plugin, app);
+               if (flatpak == NULL)
+                       return TRUE;
+       }
+
+       /* actually install */
        return gs_flatpak_app_install (flatpak, app, cancellable, error);
 }
 
@@ -425,6 +472,8 @@ gs_plugin_add_categories (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_categories (flatpak, list, cancellable, error))
                        return FALSE;
        }
@@ -441,6 +490,8 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_category_apps (flatpak,
                                                   category,
                                                   list,
@@ -461,6 +512,8 @@ gs_plugin_add_popular (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_popular (flatpak, list, cancellable, error))
                        return FALSE;
        }
@@ -476,6 +529,8 @@ gs_plugin_add_featured (GsPlugin *plugin,
        GsPluginData *priv = gs_plugin_get_data (plugin);
        for (guint i = 0; i < priv->flatpaks->len; i++) {
                GsFlatpak *flatpak = g_ptr_array_index (priv->flatpaks, i);
+               if (gs_flatpak_get_flags (flatpak) & GS_FLATPAK_FLAG_IS_TEMPORARY)
+                       continue;
                if (!gs_flatpak_add_featured (flatpak, list, cancellable, error))
                        return FALSE;
        }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]