[gnome-software/1166-repository-dialog-design-updates: 92/94] gs-plugin: Add dedicated vfunc-s to manipulate repositories




commit 076f374404e884321e719375f96b38961e19c762
Author: Milan Crha <mcrha redhat com>
Date:   Tue Jul 13 19:12:42 2021 +0200

    gs-plugin: Add dedicated vfunc-s to manipulate repositories
    
    This way it can be distinguished what operations the plugin supports
    for the repositories and it's explicit what the caller wants to do
    with the repository, instead of leaving the decision on the plugin.

 lib/gs-app.c                              |   8 +-
 lib/gs-plugin-loader.c                    |  22 +++-
 lib/gs-plugin-types.h                     |   8 ++
 lib/gs-plugin-vfuncs.h                    | 122 ++++++++++++++++++
 lib/gs-plugin.c                           |  24 ++++
 plugins/flatpak/gs-flatpak.c              |  25 +++-
 plugins/flatpak/gs-flatpak.h              |   2 +
 plugins/flatpak/gs-plugin-flatpak.c       | 132 +++++++++++++++----
 plugins/flatpak/gs-self-test.c            |  62 ++++++---
 plugins/fwupd/gs-plugin-fwupd.c           |  45 +++++--
 plugins/packagekit/gs-plugin-packagekit.c | 202 ++++++++++++++++--------------
 plugins/rpm-ostree/gs-plugin-rpm-ostree.c |  56 +++++++--
 src/gs-repos-dialog.c                     |   5 +-
 src/gs-shell.c                            |   4 +
 14 files changed, 554 insertions(+), 163 deletions(-)
---
diff --git a/lib/gs-app.c b/lib/gs-app.c
index b96733c23..930862085 100644
--- a/lib/gs-app.c
+++ b/lib/gs-app.c
@@ -1268,8 +1268,12 @@ gs_app_set_state (GsApp *app, GsAppState state)
                 * actions that usually change the state, we assign it to the
                 * appropriate action here */
                GsPluginAction action = GS_PLUGIN_ACTION_UNKNOWN;
-               if (priv->state == GS_APP_STATE_QUEUED_FOR_INSTALL)
-                       action = GS_PLUGIN_ACTION_INSTALL;
+               if (priv->state == GS_APP_STATE_QUEUED_FOR_INSTALL) {
+                       if (priv->kind == AS_COMPONENT_KIND_REPOSITORY)
+                               action = GS_PLUGIN_ACTION_INSTALL_REPO;
+                       else
+                               action = GS_PLUGIN_ACTION_INSTALL;
+               }
                gs_app_set_pending_action_internal (app, action);
 
                gs_app_queue_notify (app, obj_props[PROP_STATE]);
diff --git a/lib/gs-plugin-loader.c b/lib/gs-plugin-loader.c
index 474aad154..91c5d28a7 100644
--- a/lib/gs-plugin-loader.c
+++ b/lib/gs-plugin-loader.c
@@ -239,6 +239,10 @@ gs_plugin_loader_helper_free (GsPluginLoaderHelper *helper)
        case GS_PLUGIN_ACTION_REMOVE:
        case GS_PLUGIN_ACTION_UPDATE:
        case GS_PLUGIN_ACTION_DOWNLOAD:
+       case GS_PLUGIN_ACTION_INSTALL_REPO:
+       case GS_PLUGIN_ACTION_REMOVE_REPO:
+       case GS_PLUGIN_ACTION_ENABLE_REPO:
+       case GS_PLUGIN_ACTION_DISABLE_REPO:
                {
                        GsApp *app;
                        GsAppList *list;
@@ -674,6 +678,10 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper,
        case GS_PLUGIN_ACTION_UPDATE_CANCEL:
        case GS_PLUGIN_ACTION_ADD_SHORTCUT:
        case GS_PLUGIN_ACTION_REMOVE_SHORTCUT:
+       case GS_PLUGIN_ACTION_INSTALL_REPO:
+       case GS_PLUGIN_ACTION_REMOVE_REPO:
+       case GS_PLUGIN_ACTION_ENABLE_REPO:
+       case GS_PLUGIN_ACTION_DISABLE_REPO:
                {
                        GsPluginActionFunc plugin_func = func;
                        ret = plugin_func (plugin, app, cancellable, &error_local);
@@ -807,7 +815,7 @@ gs_plugin_loader_call_vfunc (GsPluginLoaderHelper *helper,
        }
 
        /* add app to the pending installation queue if necessary */
-       if (action == GS_PLUGIN_ACTION_INSTALL &&
+       if ((action == GS_PLUGIN_ACTION_INSTALL || action == GS_PLUGIN_ACTION_INSTALL_REPO) &&
            app != NULL && gs_app_get_state (app) == GS_APP_STATE_QUEUED_FOR_INSTALL) {
                add_app_to_install_queue (plugin_loader, app);
        }
@@ -3126,8 +3134,9 @@ gs_plugin_loader_network_changed_cb (GNetworkMonitor *monitor,
                g_mutex_unlock (&plugin_loader->pending_apps_mutex);
                for (guint i = 0; i < gs_app_list_length (queue); i++) {
                        GsApp *app = gs_app_list_index (queue, i);
+                       GsPluginAction action = gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY ? 
GS_PLUGIN_ACTION_INSTALL_REPO : GS_PLUGIN_ACTION_INSTALL;
                        g_autoptr(GsPluginJob) plugin_job = NULL;
-                       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+                       plugin_job = gs_plugin_job_newv (action,
                                                         "app", app,
                                                         NULL);
                        gs_plugin_loader_job_process_async (plugin_loader, plugin_job,
@@ -3369,6 +3378,10 @@ gs_plugin_loader_process_thread_cb (GTask *task,
        case GS_PLUGIN_ACTION_SEARCH:
        case GS_PLUGIN_ACTION_SETUP:
        case GS_PLUGIN_ACTION_UPDATE:
+       case GS_PLUGIN_ACTION_INSTALL_REPO:
+       case GS_PLUGIN_ACTION_REMOVE_REPO:
+       case GS_PLUGIN_ACTION_ENABLE_REPO:
+       case GS_PLUGIN_ACTION_DISABLE_REPO:
                if (!helper->anything_ran) {
                        g_set_error (&error,
                                     GS_PLUGIN_ERROR,
@@ -3443,6 +3456,8 @@ gs_plugin_loader_process_thread_cb (GTask *task,
        switch (action) {
        case GS_PLUGIN_ACTION_INSTALL:
        case GS_PLUGIN_ACTION_REMOVE:
+       case GS_PLUGIN_ACTION_INSTALL_REPO:
+       case GS_PLUGIN_ACTION_REMOVE_REPO:
                gs_plugin_job_add_refine_flags (helper->plugin_job,
                                                GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN |
                                                GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION);
@@ -3716,7 +3731,7 @@ gs_plugin_loader_job_process_async (GsPluginLoader *plugin_loader,
        }
 
        /* deal with the install queue */
-       if (action == GS_PLUGIN_ACTION_REMOVE) {
+       if (action == GS_PLUGIN_ACTION_REMOVE || action == GS_PLUGIN_ACTION_REMOVE_REPO) {
                if (remove_app_from_install_queue (plugin_loader, gs_plugin_job_get_app (plugin_job))) {
                        GsAppList *list = gs_plugin_job_get_list (plugin_job);
                        task = g_task_new (plugin_loader, cancellable, callback, user_data);
@@ -3897,6 +3912,7 @@ gs_plugin_loader_job_process_async (GsPluginLoader *plugin_loader,
 
        switch (action) {
        case GS_PLUGIN_ACTION_INSTALL:
+       case GS_PLUGIN_ACTION_INSTALL_REPO:
        case GS_PLUGIN_ACTION_UPDATE:
        case GS_PLUGIN_ACTION_UPGRADE_DOWNLOAD:
                /* these actions must be performed by the thread pool because we
diff --git a/lib/gs-plugin-types.h b/lib/gs-plugin-types.h
index 7365327f0..fc97b20b6 100644
--- a/lib/gs-plugin-types.h
+++ b/lib/gs-plugin-types.h
@@ -220,6 +220,10 @@ typedef enum {
  * @GS_PLUGIN_ACTION_DOWNLOAD:                 Download an application
  * @GS_PLUGIN_ACTION_GET_ALTERNATES:           Get the alternates for a specific application
  * @GS_PLUGIN_ACTION_GET_LANGPACKS:            Get appropriate language pack
+ * @GS_PLUGIN_ACTION_INSTALL_REPO:             Install a repository
+ * @GS_PLUGIN_ACTION_REMOVE_REPO:              Remove a repository
+ * @GS_PLUGIN_ACTION_ENABLE_REPO:              Enable a repository
+ * @GS_PLUGIN_ACTION_DISABLE_REPO:             Disable a repository
  *
  * The plugin action.
  **/
@@ -258,6 +262,10 @@ typedef enum {
        GS_PLUGIN_ACTION_DOWNLOAD,
        GS_PLUGIN_ACTION_GET_ALTERNATES,
        GS_PLUGIN_ACTION_GET_LANGPACKS,
+       GS_PLUGIN_ACTION_INSTALL_REPO,
+       GS_PLUGIN_ACTION_REMOVE_REPO,
+       GS_PLUGIN_ACTION_ENABLE_REPO,
+       GS_PLUGIN_ACTION_DISABLE_REPO,
        GS_PLUGIN_ACTION_LAST  /*< skip >*/
 } GsPluginAction;
 
diff --git a/lib/gs-plugin-vfuncs.h b/lib/gs-plugin-vfuncs.h
index e9dcb226d..aa30647af 100644
--- a/lib/gs-plugin-vfuncs.h
+++ b/lib/gs-plugin-vfuncs.h
@@ -803,4 +803,126 @@ gboolean   gs_plugin_add_langpacks                (GsPlugin       *plugin,
                                                         GCancellable   *cancellable,
                                                         GError         **error);
 
+/**
+ * gs_plugin_repo_install:
+ * @plugin: a #GsPlugin
+ * @repo: a #GsApp representing a repository
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Install the repository. This is a voluntary function, the plugin implements
+ * it only if it supports it. If implemented, its pair function gs_plugin_repo_remove()
+ * should be implemented as well.
+ *
+ * Plugins are expected to send progress notifications to the UI using
+ * gs_app_set_progress() using the passed in @repo.
+ *
+ * All functions can block, but should sent progress notifications, e.g. using
+ * gs_app_set_progress() if they will take more than tens of milliseconds
+ * to complete.
+ *
+ * On failure the error message returned will usually only be shown on the
+ * console, but they can also be retrieved using gs_plugin_loader_get_events().
+ *
+ * NOTE: Once the action is complete, the plugin must set the new state of @repo
+ * to either %GS_APP_STATE_INSTALLED or %GS_APP_STATE_AVAILABLE.
+ *
+ * Returns: %TRUE for success or if not relevant
+ **/
+gboolean        gs_plugin_repo_install                 (GsPlugin       *plugin,
+                                                        GsApp          *repo,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+
+/**
+ * gs_plugin_repo_remove:
+ * @plugin: a #GsPlugin
+ * @repo: a #GsApp representing a repository
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Remove the repository. This is a voluntary function, the plugin implements
+ * it only if it supports it. If implemented, its pair function gs_plugin_repo_install()
+ * should be implemented as well.
+ *
+ * Plugins are expected to send progress notifications to the UI using
+ * gs_app_set_progress() using the passed in @app.
+ *
+ * All functions can block, but should sent progress notifications, e.g. using
+ * gs_app_set_progress() if they will take more than tens of milliseconds
+ * to complete.
+ *
+ * On failure the error message returned will usually only be shown on the
+ * console, but they can also be retrieved using gs_plugin_loader_get_events().
+ *
+ * NOTE: Once the action is complete, the plugin must set the new state of @app
+ * to %GS_APP_STATE_AVAILABLE or %GS_APP_STATE_UNKNOWN if not known.
+ *
+ * Returns: %TRUE for success or if not relevant
+ **/
+gboolean        gs_plugin_repo_remove                  (GsPlugin       *plugin,
+                                                        GsApp          *repo,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+/**
+ * gs_plugin_repo_enable:
+ * @plugin: a #GsPlugin
+ * @repo: a #GsApp representing a repository
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Enable the repository. This is a voluntary function, the plugin implements
+ * it only if it supports it. If implemented, its pair function gs_plugin_repo_disable()
+ * should be implemented as well.
+ *
+ * Plugins are expected to send progress notifications to the UI using
+ * gs_app_set_progress() using the passed in @repo.
+ *
+ * All functions can block, but should sent progress notifications, e.g. using
+ * gs_app_set_progress() if they will take more than tens of milliseconds
+ * to complete.
+ *
+ * On failure the error message returned will usually only be shown on the
+ * console, but they can also be retrieved using gs_plugin_loader_get_events().
+ *
+ * NOTE: Once the action is complete, the plugin must set the new state of @repo
+ * to %GS_APP_STATE_INSTALLED.
+ *
+ * Returns: %TRUE for success or if not relevant
+ **/
+gboolean        gs_plugin_repo_enable                  (GsPlugin       *plugin,
+                                                        GsApp          *repo,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
+
+/**
+ * gs_plugin_repo_disable:
+ * @plugin: a #GsPlugin
+ * @repo: a #GsApp representing a repository
+ * @cancellable: a #GCancellable, or %NULL
+ * @error: a #GError, or %NULL
+ *
+ * Disable the repository. This is a voluntary function, the plugin implements
+ * it only if it supports it. If implemented, its pair function gs_plugin_repo_enable()
+ * should be implemented as well.
+ *
+ * Plugins are expected to send progress notifications to the UI using
+ * gs_app_set_progress() using the passed in @app.
+ *
+ * All functions can block, but should sent progress notifications, e.g. using
+ * gs_app_set_progress() if they will take more than tens of milliseconds
+ * to complete.
+ *
+ * On failure the error message returned will usually only be shown on the
+ * console, but they can also be retrieved using gs_plugin_loader_get_events().
+ *
+ * NOTE: Once the action is complete, the plugin must set the new state of @app
+ * to %GS_APP_STATE_AVAILABLE.
+ *
+ * Returns: %TRUE for success or if not relevant
+ **/
+gboolean        gs_plugin_repo_disable                 (GsPlugin       *plugin,
+                                                        GsApp          *repo,
+                                                        GCancellable   *cancellable,
+                                                        GError         **error);
 G_END_DECLS
diff --git a/lib/gs-plugin.c b/lib/gs-plugin.c
index 3ef285b8f..0116af140 100644
--- a/lib/gs-plugin.c
+++ b/lib/gs-plugin.c
@@ -1646,6 +1646,14 @@ gs_plugin_action_to_function_name (GsPluginAction action)
                return "gs_plugin_add_alternates";
        if (action == GS_PLUGIN_ACTION_GET_LANGPACKS)
                return "gs_plugin_add_langpacks";
+       if (action == GS_PLUGIN_ACTION_INSTALL_REPO)
+               return "gs_plugin_repo_install";
+       if (action == GS_PLUGIN_ACTION_REMOVE_REPO)
+               return "gs_plugin_repo_remove";
+       if (action == GS_PLUGIN_ACTION_ENABLE_REPO)
+               return "gs_plugin_repo_enable";
+       if (action == GS_PLUGIN_ACTION_DISABLE_REPO)
+               return "gs_plugin_repo_disable";
        return NULL;
 }
 
@@ -1728,6 +1736,14 @@ gs_plugin_action_to_string (GsPluginAction action)
                return "get-alternates";
        if (action == GS_PLUGIN_ACTION_GET_LANGPACKS)
                return "get-langpacks";
+       if (action == GS_PLUGIN_ACTION_INSTALL_REPO)
+               return "repo-install";
+       if (action == GS_PLUGIN_ACTION_REMOVE_REPO)
+               return "repo-remove";
+       if (action == GS_PLUGIN_ACTION_ENABLE_REPO)
+               return "repo-enable";
+       if (action == GS_PLUGIN_ACTION_DISABLE_REPO)
+               return "repo-disable";
        return NULL;
 }
 
@@ -1810,6 +1826,14 @@ gs_plugin_action_from_string (const gchar *action)
                return GS_PLUGIN_ACTION_GET_ALTERNATES;
        if (g_strcmp0 (action, "get-langpacks") == 0)
                return GS_PLUGIN_ACTION_GET_LANGPACKS;
+       if (g_strcmp0 (action, "repo-install") == 0)
+               return GS_PLUGIN_ACTION_INSTALL_REPO;
+       if (g_strcmp0 (action, "repo-remove") == 0)
+               return GS_PLUGIN_ACTION_REMOVE_REPO;
+       if (g_strcmp0 (action, "repo-enable") == 0)
+               return GS_PLUGIN_ACTION_ENABLE_REPO;
+       if (g_strcmp0 (action, "repo-disable") == 0)
+               return GS_PLUGIN_ACTION_DISABLE_REPO;
        return GS_PLUGIN_ACTION_UNKNOWN;
 }
 
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index f1f87f61a..bcab0b7c8 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -1567,7 +1567,9 @@ gs_flatpak_create_new_remote (GsFlatpak *self,
 }
 
 gboolean
-gs_flatpak_app_install_source (GsFlatpak *self, GsApp *app,
+gs_flatpak_app_install_source (GsFlatpak *self,
+                              GsApp *app,
+                              gboolean is_install,
                               GCancellable *cancellable,
                               GError **error)
 {
@@ -1580,6 +1582,8 @@ gs_flatpak_app_install_source (GsFlatpak *self, GsApp *app,
                /* if the remote already exists, just enable it */
                g_debug ("enabling existing remote %s", flatpak_remote_get_name (xremote));
                flatpak_remote_set_disabled (xremote, FALSE);
+       } else if (!is_install) {
+               g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "Cannot enable flatpak remote 
'%s', remote not found", gs_app_get_id (app));
        } else {
                /* create a new remote */
                xremote = gs_flatpak_create_new_remote (self, app, cancellable, error);
@@ -3164,10 +3168,12 @@ gs_flatpak_launch (GsFlatpak *self,
 gboolean
 gs_flatpak_app_remove_source (GsFlatpak *self,
                              GsApp *app,
+                             gboolean is_remove,
                              GCancellable *cancellable,
                              GError **error)
 {
        g_autoptr(FlatpakRemote) xremote = NULL;
+       gboolean success;
 
        /* find the remote */
        xremote = flatpak_installation_get_remote_by_name (self->installation,
@@ -3183,10 +3189,17 @@ gs_flatpak_app_remove_source (GsFlatpak *self,
 
        /* remove */
        gs_app_set_state (app, GS_APP_STATE_REMOVING);
-       if (!flatpak_installation_remove_remote (self->installation,
-                                                gs_app_get_id (app),
-                                                cancellable,
-                                                error)) {
+       if (is_remove) {
+               success = flatpak_installation_remove_remote (self->installation, gs_app_get_id (app), 
cancellable, error);
+       } else {
+               gboolean was_disabled = flatpak_remote_get_disabled (xremote);
+               flatpak_remote_set_disabled (xremote, TRUE);
+               success = flatpak_installation_modify_remote (self->installation, xremote, cancellable, 
error);
+               if (!success)
+                       flatpak_remote_set_disabled (xremote, was_disabled);
+       }
+
+       if (!success) {
                gs_flatpak_error_convert (error);
                gs_app_set_state_recover (app);
                return FALSE;
@@ -3198,7 +3211,7 @@ gs_flatpak_app_remove_source (GsFlatpak *self,
                xb_silo_invalidate (self->silo);
        g_rw_lock_reader_unlock (&self->silo_lock);
 
-       gs_app_set_state (app, GS_APP_STATE_UNAVAILABLE);
+       gs_app_set_state (app, is_remove ? GS_APP_STATE_UNAVAILABLE : GS_APP_STATE_AVAILABLE);
 
        gs_plugin_repository_changed (self->plugin, app);
 
diff --git a/plugins/flatpak/gs-flatpak.h b/plugins/flatpak/gs-flatpak.h
index 5eb7bb452..5416019d6 100644
--- a/plugins/flatpak/gs-flatpak.h
+++ b/plugins/flatpak/gs-flatpak.h
@@ -78,10 +78,12 @@ gboolean    gs_flatpak_launch               (GsFlatpak              *self,
                                                 GError                 **error);
 gboolean       gs_flatpak_app_remove_source    (GsFlatpak              *self,
                                                 GsApp                  *app,
+                                                gboolean                is_remove,
                                                 GCancellable           *cancellable,
                                                 GError                 **error);
 gboolean       gs_flatpak_app_install_source   (GsFlatpak              *self,
                                                 GsApp                  *app,
+                                                gboolean                is_install,
                                                 GCancellable           *cancellable,
                                                 GError                 **error);
 GsApp          *gs_flatpak_file_to_app_ref     (GsFlatpak              *self,
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
index 364bc27d1..b3ae14c27 100644
--- a/plugins/flatpak/gs-plugin-flatpak.c
+++ b/plugins/flatpak/gs-plugin-flatpak.c
@@ -865,9 +865,8 @@ gs_plugin_app_remove (GsPlugin *plugin,
        if (flatpak == NULL)
                return TRUE;
 
-       /* is a source */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY)
-               return gs_flatpak_app_remove_source (flatpak, app, cancellable, error);
+       /* is a source, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
 
        /* build and run transaction */
        transaction = _build_transaction (plugin, flatpak, cancellable, error);
@@ -929,13 +928,35 @@ app_has_local_source (GsApp *app)
        return FALSE;
 }
 
+static void
+gs_plugin_flatpak_ensure_scope (GsPlugin *plugin,
+                               GsApp *app)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+
+       if (gs_app_get_scope (app) == AS_COMPONENT_SCOPE_UNKNOWN) {
+               g_autoptr(GSettings) settings = g_settings_new ("org.gnome.software");
+
+               /* get the new GsFlatpak for handling of local files */
+               gs_app_set_scope (app, g_settings_get_boolean (settings, "install-bundles-system-wide") ?
+                                       AS_COMPONENT_SCOPE_SYSTEM : AS_COMPONENT_SCOPE_USER);
+               if (!priv->has_system_helper) {
+                       g_info ("no flatpak system helper is available, using user");
+                       gs_app_set_scope (app, AS_COMPONENT_SCOPE_USER);
+               }
+               if (priv->destdir_for_tests != NULL) {
+                       g_debug ("in self tests, using user");
+                       gs_app_set_scope (app, AS_COMPONENT_SCOPE_USER);
+               }
+       }
+}
+
 gboolean
 gs_plugin_app_install (GsPlugin *plugin,
                       GsApp *app,
                       GCancellable *cancellable,
                       GError **error)
 {
-       GsPluginData *priv = gs_plugin_get_data (plugin);
        GsFlatpak *flatpak;
        g_autoptr(FlatpakTransaction) transaction = NULL;
        g_autoptr(GError) error_local = NULL;
@@ -949,31 +970,15 @@ gs_plugin_app_install (GsPlugin *plugin,
                return TRUE;
        }
 
-       /* set the app scope */
-       if (gs_app_get_scope (app) == AS_COMPONENT_SCOPE_UNKNOWN) {
-               g_autoptr(GSettings) settings = g_settings_new ("org.gnome.software");
-
-               /* get the new GsFlatpak for handling of local files */
-               gs_app_set_scope (app, g_settings_get_boolean (settings, "install-bundles-system-wide") ?
-                                       AS_COMPONENT_SCOPE_SYSTEM : AS_COMPONENT_SCOPE_USER);
-               if (!priv->has_system_helper) {
-                       g_info ("no flatpak system helper is available, using user");
-                       gs_app_set_scope (app, AS_COMPONENT_SCOPE_USER);
-               }
-               if (priv->destdir_for_tests != NULL) {
-                       g_debug ("in self tests, using user");
-                       gs_app_set_scope (app, AS_COMPONENT_SCOPE_USER);
-               }
-       }
+       gs_plugin_flatpak_ensure_scope (plugin, app);
 
        /* not supported */
        flatpak = gs_plugin_flatpak_get_handler (plugin, app);
        if (flatpak == NULL)
                return TRUE;
 
-       /* is a source */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY)
-               return gs_flatpak_app_install_source (flatpak, app, cancellable, error);
+       /* is a source, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
 
        /* build */
        transaction = _build_transaction (plugin, flatpak, cancellable, error);
@@ -1559,3 +1564,84 @@ gs_plugin_add_recent (GsPlugin *plugin,
        }
        return TRUE;
 }
+
+gboolean
+gs_plugin_repo_install (GsPlugin *plugin,
+                       GsApp *repo,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+       GsFlatpak *flatpak;
+
+       /* queue for install if installation needs the network */
+       if (!app_has_local_source (repo) &&
+           !gs_plugin_get_network_available (plugin)) {
+               gs_app_set_state (repo, GS_APP_STATE_QUEUED_FOR_INSTALL);
+               return TRUE;
+       }
+
+       gs_plugin_flatpak_ensure_scope (plugin, repo);
+
+       flatpak = gs_plugin_flatpak_get_handler (plugin, repo);
+       if (flatpak == NULL)
+               return TRUE;
+
+       /* is a source */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       return gs_flatpak_app_install_source (flatpak, repo, TRUE, cancellable, error);
+}
+
+gboolean
+gs_plugin_repo_remove (GsPlugin *plugin,
+                      GsApp *repo,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       GsFlatpak *flatpak;
+
+       flatpak = gs_plugin_flatpak_get_handler (plugin, repo);
+       if (flatpak == NULL)
+               return TRUE;
+
+       /* is a source */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       return gs_flatpak_app_remove_source (flatpak, repo, TRUE, cancellable, error);
+}
+
+gboolean
+gs_plugin_repo_enable (GsPlugin *plugin,
+                      GsApp *repo,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       GsFlatpak *flatpak;
+
+       flatpak = gs_plugin_flatpak_get_handler (plugin, repo);
+       if (flatpak == NULL)
+               return TRUE;
+
+       /* is a source */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       return gs_flatpak_app_install_source (flatpak, repo, FALSE, cancellable, error);
+}
+
+gboolean
+gs_plugin_repo_disable (GsPlugin *plugin,
+                       GsApp *repo,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+       GsFlatpak *flatpak;
+
+       flatpak = gs_plugin_flatpak_get_handler (plugin, repo);
+       if (flatpak == NULL)
+               return TRUE;
+
+       /* is a source */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       return gs_flatpak_app_remove_source (flatpak, repo, FALSE, cancellable, error);
+}
diff --git a/plugins/flatpak/gs-self-test.c b/plugins/flatpak/gs-self-test.c
index e17eaf385..330855c96 100644
--- a/plugins/flatpak/gs-self-test.c
+++ b/plugins/flatpak/gs-self-test.c
@@ -156,7 +156,7 @@ gs_plugins_flatpak_repo_func (GsPluginLoader *plugin_loader)
 
        /* now install the remote */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -193,9 +193,33 @@ gs_plugins_flatpak_repo_func (GsPluginLoader *plugin_loader)
        g_assert_true (app2 != NULL);
        g_assert_cmpint (gs_app_get_state (app2), ==, GS_APP_STATE_INSTALLED);
 
+       /* disable repo */
+       g_object_unref (plugin_job);
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_DISABLE_REPO,
+                                        "app", app,
+                                        NULL);
+       ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+       gs_test_flush_main_context ();
+       g_assert_no_error (error);
+       g_assert_true (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_AVAILABLE);
+       g_assert_cmpint (gs_app_get_progress (app), ==, GS_APP_PROGRESS_UNKNOWN);
+
+       /* enable repo */
+       g_object_unref (plugin_job);
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_ENABLE_REPO,
+                                        "app", app,
+                                        NULL);
+       ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
+       gs_test_flush_main_context ();
+       g_assert_no_error (error);
+       g_assert_true (ret);
+       g_assert_cmpint (gs_app_get_state (app), ==, GS_APP_STATE_INSTALLED);
+       g_assert_cmpint (gs_app_get_progress (app), ==, GS_APP_PROGRESS_UNKNOWN);
+
        /* remove it */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -284,7 +308,7 @@ gs_plugins_flatpak_app_with_runtime_func (GsPluginLoader *plugin_loader)
        gs_app_set_management_plugin (app_source, "flatpak");
        gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
        gs_flatpak_app_set_repo_url (app_source, testdir_repourl);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -477,7 +501,7 @@ gs_plugins_flatpak_app_with_runtime_func (GsPluginLoader *plugin_loader)
 
        /* remove the remote (fail, as the runtime is still installed) */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -499,7 +523,7 @@ gs_plugins_flatpak_app_with_runtime_func (GsPluginLoader *plugin_loader)
 
        /* remove the remote */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -548,7 +572,7 @@ gs_plugins_flatpak_app_missing_runtime_func (GsPluginLoader *plugin_loader)
        gs_app_set_management_plugin (app_source, "flatpak");
        gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
        gs_flatpak_app_set_repo_url (app_source, testdir_repourl);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -597,7 +621,7 @@ gs_plugins_flatpak_app_missing_runtime_func (GsPluginLoader *plugin_loader)
 
        /* remove the remote */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -772,7 +796,7 @@ gs_plugins_flatpak_runtime_repo_func (GsPluginLoader *plugin_loader)
        g_assert_true (app_source != NULL);
        g_assert_cmpstr (gs_app_get_unique_id (app_source), ==, "user/flatpak/*/test/*");
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -835,7 +859,7 @@ gs_plugins_flatpak_runtime_repo_redundant_func (GsPluginLoader *plugin_loader)
 
        /* install the source manually */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_src,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -933,7 +957,7 @@ gs_plugins_flatpak_runtime_repo_redundant_func (GsPluginLoader *plugin_loader)
        g_assert_true (app_source != NULL);
        g_assert_cmpstr (gs_app_get_unique_id (app_source), ==, "user/flatpak/*/test/*");
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -977,7 +1001,7 @@ gs_plugins_flatpak_broken_remote_func (GsPluginLoader *plugin_loader)
        gs_app_set_management_plugin (app_source, "flatpak");
        gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
        gs_flatpak_app_set_repo_url (app_source, "file:///wont/work");
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1029,7 +1053,7 @@ gs_plugins_flatpak_broken_remote_func (GsPluginLoader *plugin_loader)
 
        /* remove source */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1077,7 +1101,7 @@ flatpak_bundle_or_ref_helper (GsPluginLoader *plugin_loader,
        gs_app_set_management_plugin (app_source, "flatpak");
        gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
        gs_flatpak_app_set_repo_url (app_source, testdir_repourl);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1272,7 +1296,7 @@ flatpak_bundle_or_ref_helper (GsPluginLoader *plugin_loader,
 
        /* remove source */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1286,7 +1310,7 @@ flatpak_bundle_or_ref_helper (GsPluginLoader *plugin_loader,
                gs_app_set_management_plugin (runtime_source, "flatpak");
                gs_app_set_state (runtime_source, GS_APP_STATE_INSTALLED);
                g_object_unref (plugin_job);
-               plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+               plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                                 "app", runtime_source,
                                                 NULL);
                ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1395,7 +1419,7 @@ gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
        gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
        repo_url = g_strdup_printf ("file://%s", repo_path);
        gs_flatpak_app_set_repo_url (app_source, repo_url);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1577,7 +1601,7 @@ gs_plugins_flatpak_app_update_func (GsPluginLoader *plugin_loader)
 
        /* remove the remote */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1646,7 +1670,7 @@ gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
        gs_app_set_state (app_source, GS_APP_STATE_AVAILABLE);
        repo_url = g_strdup_printf ("file://%s", repo_path);
        gs_flatpak_app_set_repo_url (app_source, repo_url);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_INSTALL_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
@@ -1839,7 +1863,7 @@ gs_plugins_flatpak_runtime_extension_func (GsPluginLoader *plugin_loader)
 
        /* remove the remote */
        g_object_unref (plugin_job);
-       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE,
+       plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_REMOVE_REPO,
                                         "app", app_source,
                                         NULL);
        ret = gs_plugin_loader_job_action (plugin_loader, plugin_job, NULL, &error);
diff --git a/plugins/fwupd/gs-plugin-fwupd.c b/plugins/fwupd/gs-plugin-fwupd.c
index 3ce397cac..58293e89c 100644
--- a/plugins/fwupd/gs-plugin-fwupd.c
+++ b/plugins/fwupd/gs-plugin-fwupd.c
@@ -970,11 +970,8 @@ gs_plugin_app_install (GsPlugin *plugin,
                       gs_plugin_get_name (plugin)) != 0)
                return TRUE;
 
-       /* source -> remote */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY) {
-               return gs_plugin_fwupd_modify_source (plugin, app, TRUE,
-                                                     cancellable, error);
-       }
+       /* source -> remote, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
 
        /* firmware */
        return gs_plugin_fwupd_install (plugin, app, cancellable, error);
@@ -989,8 +986,8 @@ gs_plugin_app_remove (GsPlugin *plugin, GsApp *app,
                       gs_plugin_get_name (plugin)) != 0)
                return TRUE;
 
-       /* source -> remote */
-       return gs_plugin_fwupd_modify_source (plugin, app, FALSE, cancellable, error);
+       g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_NOT_SUPPORTED, "Removal of '%s' not supported", 
gs_app_get_management_plugin (app));
+       return FALSE;
 }
 
 gboolean
@@ -1194,3 +1191,37 @@ gs_plugin_add_sources (GsPlugin *plugin,
        }
        return TRUE;
 }
+
+gboolean
+gs_plugin_repo_enable (GsPlugin *plugin,
+                      GsApp *repo,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       /* only process this app if it was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (repo),
+                      gs_plugin_get_name (plugin)) != 0)
+               return TRUE;
+
+       /* source -> remote */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       return gs_plugin_fwupd_modify_source (plugin, repo, TRUE, cancellable, error);
+}
+
+gboolean
+gs_plugin_repo_disable (GsPlugin *plugin,
+                       GsApp *repo,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+       /* only process this app if it was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (repo),
+                      gs_plugin_get_name (plugin)) != 0)
+               return TRUE;
+
+       /* source -> remote */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       return gs_plugin_fwupd_modify_source (plugin, repo, FALSE, cancellable, error);
+}
diff --git a/plugins/packagekit/gs-plugin-packagekit.c b/plugins/packagekit/gs-plugin-packagekit.c
index 8988db2f9..d8bd56ec0 100644
--- a/plugins/packagekit/gs-plugin-packagekit.c
+++ b/plugins/packagekit/gs-plugin-packagekit.c
@@ -362,50 +362,6 @@ gs_plugin_app_origin_repo_enable (GsPlugin *plugin,
        return TRUE;
 }
 
-static gboolean
-gs_plugin_repo_enable (GsPlugin *plugin,
-                       GsApp *app,
-                       GCancellable *cancellable,
-                       GError **error)
-{
-       GsPluginData *priv = gs_plugin_get_data (plugin);
-       g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
-       g_autoptr(PkResults) results = NULL;
-       g_autoptr(PkError) error_code = NULL;
-
-       /* do sync call */
-       gs_plugin_status_update (plugin, app, GS_PLUGIN_STATUS_WAITING);
-       gs_app_set_state (app, GS_APP_STATE_INSTALLING);
-       gs_packagekit_helper_add_app (helper, app);
-       g_mutex_lock (&priv->task_mutex);
-       pk_client_set_interactive (PK_CLIENT (priv->task), gs_plugin_has_flags (plugin, 
GS_PLUGIN_FLAGS_INTERACTIVE));
-       results = pk_client_repo_enable (PK_CLIENT (priv->task),
-                                        gs_app_get_id (app),
-                                        TRUE,
-                                        cancellable,
-                                        gs_packagekit_helper_cb, helper,
-                                        error);
-       g_mutex_unlock (&priv->task_mutex);
-
-       /* pk_client_repo_enable() returns an error if the repo is already enabled. */
-       if (results != NULL &&
-           (error_code = pk_results_get_error_code (results)) != NULL &&
-           pk_error_get_code (error_code) == PK_ERROR_ENUM_REPO_ALREADY_SET) {
-               g_clear_error (error);
-       } else if (!gs_plugin_packagekit_results_valid (results, error)) {
-               gs_app_set_state_recover (app);
-               gs_utils_error_add_origin_id (error, app);
-               return FALSE;
-       }
-
-       /* state is known */
-       gs_app_set_state (app, GS_APP_STATE_INSTALLED);
-
-       gs_plugin_repository_changed (plugin, app);
-
-       return TRUE;
-}
-
 gboolean
 gs_plugin_app_install (GsPlugin *plugin,
                       GsApp *app,
@@ -428,9 +384,8 @@ gs_plugin_app_install (GsPlugin *plugin,
                       gs_plugin_get_name (plugin)) != 0)
                return TRUE;
 
-       /* enable repo */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY)
-               return gs_plugin_repo_enable (plugin, app, cancellable, error);
+       /* enable repo, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
 
        /* queue for install if installation needs the network */
        if (!gs_plugin_get_network_available (plugin)) {
@@ -616,50 +571,6 @@ gs_plugin_app_install (GsPlugin *plugin,
        return TRUE;
 }
 
-static gboolean
-gs_plugin_repo_disable (GsPlugin *plugin,
-                        GsApp *app,
-                        GCancellable *cancellable,
-                        GError **error)
-{
-       GsPluginData *priv = gs_plugin_get_data (plugin);
-       g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
-       g_autoptr(PkResults) results = NULL;
-       g_autoptr(PkError) error_code = NULL;
-
-       /* do sync call */
-       gs_plugin_status_update (plugin, app, GS_PLUGIN_STATUS_WAITING);
-       gs_app_set_state (app, GS_APP_STATE_REMOVING);
-       gs_packagekit_helper_add_app (helper, app);
-       g_mutex_lock (&priv->task_mutex);
-       pk_client_set_interactive (PK_CLIENT (priv->task), gs_plugin_has_flags (plugin, 
GS_PLUGIN_FLAGS_INTERACTIVE));
-       results = pk_client_repo_enable (PK_CLIENT (priv->task),
-                                        gs_app_get_id (app),
-                                        FALSE,
-                                        cancellable,
-                                        gs_packagekit_helper_cb, helper,
-                                        error);
-       g_mutex_unlock (&priv->task_mutex);
-
-       /* pk_client_repo_enable() returns an error if the repo is already enabled. */
-       if (results != NULL &&
-           (error_code = pk_results_get_error_code (results)) != NULL &&
-           pk_error_get_code (error_code) == PK_ERROR_ENUM_REPO_ALREADY_SET) {
-               g_clear_error (error);
-       } else if (!gs_plugin_packagekit_results_valid (results, error)) {
-               gs_app_set_state_recover (app);
-               gs_utils_error_add_origin_id (error, app);
-               return FALSE;
-       }
-
-       /* state is known */
-       gs_app_set_state (app, GS_APP_STATE_AVAILABLE);
-
-       gs_plugin_repository_changed (plugin, app);
-
-       return TRUE;
-}
-
 gboolean
 gs_plugin_app_remove (GsPlugin *plugin,
                      GsApp *app,
@@ -681,9 +592,8 @@ gs_plugin_app_remove (GsPlugin *plugin,
                       gs_plugin_get_name (plugin)) != 0)
                return TRUE;
 
-       /* disable repo */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY)
-               return gs_plugin_repo_disable (plugin, app, cancellable, error);
+       /* disable repo, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
 
        /* get the list of available package ids to install */
        source_ids = gs_app_get_source_ids (app);
@@ -2638,3 +2548,107 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin,
        gs_app_set_state (app, GS_APP_STATE_UPDATABLE);
        return TRUE;
 }
+
+gboolean
+gs_plugin_repo_enable (GsPlugin *plugin,
+                      GsApp *repo,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
+       g_autoptr(PkResults) results = NULL;
+       g_autoptr(PkError) error_code = NULL;
+
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (repo),
+                      gs_plugin_get_name (plugin)) != 0)
+               return TRUE;
+
+       /* is repo */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       /* do sync call */
+       gs_plugin_status_update (plugin, repo, GS_PLUGIN_STATUS_WAITING);
+       gs_app_set_state (repo, GS_APP_STATE_INSTALLING);
+       gs_packagekit_helper_add_app (helper, repo);
+       g_mutex_lock (&priv->task_mutex);
+       pk_client_set_interactive (PK_CLIENT (priv->task), gs_plugin_has_flags (plugin, 
GS_PLUGIN_FLAGS_INTERACTIVE));
+       results = pk_client_repo_enable (PK_CLIENT (priv->task),
+                                        gs_app_get_id (repo),
+                                        TRUE,
+                                        cancellable,
+                                        gs_packagekit_helper_cb, helper,
+                                        error);
+       g_mutex_unlock (&priv->task_mutex);
+
+       /* pk_client_repo_enable() returns an error if the repo is already enabled. */
+       if (results != NULL &&
+           (error_code = pk_results_get_error_code (results)) != NULL &&
+           pk_error_get_code (error_code) == PK_ERROR_ENUM_REPO_ALREADY_SET) {
+               g_clear_error (error);
+       } else if (!gs_plugin_packagekit_results_valid (results, error)) {
+               gs_app_set_state_recover (repo);
+               gs_utils_error_add_origin_id (error, repo);
+               return FALSE;
+       }
+
+       /* state is known */
+       gs_app_set_state (repo, GS_APP_STATE_INSTALLED);
+
+       gs_plugin_repository_changed (plugin, repo);
+
+       return TRUE;
+}
+
+gboolean
+gs_plugin_repo_disable (GsPlugin *plugin,
+                       GsApp *repo,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+       GsPluginData *priv = gs_plugin_get_data (plugin);
+       g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
+       g_autoptr(PkResults) results = NULL;
+       g_autoptr(PkError) error_code = NULL;
+
+       /* only process this app if was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (repo),
+                      gs_plugin_get_name (plugin)) != 0)
+               return TRUE;
+
+       /* is repo */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       /* do sync call */
+       gs_plugin_status_update (plugin, repo, GS_PLUGIN_STATUS_WAITING);
+       gs_app_set_state (repo, GS_APP_STATE_REMOVING);
+       gs_packagekit_helper_add_app (helper, repo);
+       g_mutex_lock (&priv->task_mutex);
+       pk_client_set_interactive (PK_CLIENT (priv->task), gs_plugin_has_flags (plugin, 
GS_PLUGIN_FLAGS_INTERACTIVE));
+       results = pk_client_repo_enable (PK_CLIENT (priv->task),
+                                        gs_app_get_id (repo),
+                                        FALSE,
+                                        cancellable,
+                                        gs_packagekit_helper_cb, helper,
+                                        error);
+       g_mutex_unlock (&priv->task_mutex);
+
+       /* pk_client_repo_enable() returns an error if the repo is already enabled. */
+       if (results != NULL &&
+           (error_code = pk_results_get_error_code (results)) != NULL &&
+           pk_error_get_code (error_code) == PK_ERROR_ENUM_REPO_ALREADY_SET) {
+               g_clear_error (error);
+       } else if (!gs_plugin_packagekit_results_valid (results, error)) {
+               gs_app_set_state_recover (repo);
+               gs_utils_error_add_origin_id (error, repo);
+               return FALSE;
+       }
+
+       /* state is known */
+       gs_app_set_state (repo, GS_APP_STATE_AVAILABLE);
+
+       gs_plugin_repository_changed (plugin, repo);
+
+       return TRUE;
+}
diff --git a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
index 6b1a13519..ecac4d974 100644
--- a/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
+++ b/plugins/rpm-ostree/gs-plugin-rpm-ostree.c
@@ -1316,13 +1316,12 @@ gs_plugin_app_install (GsPlugin *plugin,
        if (g_strcmp0 (gs_app_get_management_plugin (app), gs_plugin_get_name (plugin)) != 0)
                return TRUE;
 
+       /* enable repo, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
        if (!gs_rpmostree_ref_proxies (plugin, &os_proxy, &sysroot_proxy, cancellable, error))
                return FALSE;
 
-       /* enable repo */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY)
-               return gs_rpmostree_repo_enable (plugin, app, TRUE, os_proxy, sysroot_proxy, cancellable, 
error);
-
        switch (gs_app_get_state (app)) {
        case GS_APP_STATE_AVAILABLE:
                if (gs_app_get_source_default (app) == NULL) {
@@ -1422,9 +1421,8 @@ gs_plugin_app_remove (GsPlugin *plugin,
        if (!gs_rpmostree_ref_proxies (plugin, &os_proxy, &sysroot_proxy, cancellable, error))
                return FALSE;
 
-       /* disable repo */
-       if (gs_app_get_kind (app) == AS_COMPONENT_KIND_REPOSITORY)
-               return gs_rpmostree_repo_enable (plugin, app, FALSE, os_proxy, sysroot_proxy, cancellable, 
error);
+       /* disable repo, handled by dedicated function */
+       g_return_val_if_fail (gs_app_get_kind (app) != AS_COMPONENT_KIND_REPOSITORY, FALSE);
 
        gs_app_set_state (app, GS_APP_STATE_REMOVING);
        tp->app = g_object_ref (app);
@@ -2152,3 +2150,47 @@ gs_plugin_add_sources (GsPlugin *plugin,
 
        return TRUE;
 }
+
+gboolean
+gs_plugin_repo_enable (GsPlugin *plugin,
+                      GsApp *repo,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       g_autoptr(GsRPMOSTreeOS) os_proxy = NULL;
+       g_autoptr(GsRPMOSTreeSysroot) sysroot_proxy = NULL;
+
+       /* only process this app if it was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (repo), gs_plugin_get_name (plugin)) != 0)
+               return TRUE;
+
+       /* enable repo */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       if (!gs_rpmostree_ref_proxies (plugin, &os_proxy, &sysroot_proxy, cancellable, error))
+               return FALSE;
+
+       return gs_rpmostree_repo_enable (plugin, repo, TRUE, os_proxy, sysroot_proxy, cancellable, error);
+}
+
+gboolean
+gs_plugin_repo_disable (GsPlugin *plugin,
+                       GsApp *repo,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+       g_autoptr(GsRPMOSTreeOS) os_proxy = NULL;
+       g_autoptr(GsRPMOSTreeSysroot) sysroot_proxy = NULL;
+
+       /* only process this app if it was created by this plugin */
+       if (g_strcmp0 (gs_app_get_management_plugin (repo), gs_plugin_get_name (plugin)) != 0)
+               return TRUE;
+
+       /* disable repo */
+       g_return_val_if_fail (gs_app_get_kind (repo) == AS_COMPONENT_KIND_REPOSITORY, FALSE);
+
+       if (!gs_rpmostree_ref_proxies (plugin, &os_proxy, &sysroot_proxy, cancellable, error))
+               return FALSE;
+
+       return gs_rpmostree_repo_enable (plugin, repo, FALSE, os_proxy, sysroot_proxy, cancellable, error);
+}
diff --git a/src/gs-repos-dialog.c b/src/gs-repos-dialog.c
index 3d00b2510..e631cadd0 100644
--- a/src/gs-repos-dialog.c
+++ b/src/gs-repos-dialog.c
@@ -206,7 +206,7 @@ enable_repo (GsReposDialog *dialog, GsApp *repo)
        g_autoptr(InstallRemoveData) install_data = NULL;
 
        install_data = g_slice_new0 (InstallRemoveData);
-       install_data->action = GS_PLUGIN_ACTION_INSTALL;
+       install_data->action = GS_PLUGIN_ACTION_ENABLE_REPO;
        install_data->repo = g_object_ref (repo);
        install_data->dialog = g_object_ref (dialog);
 
@@ -291,16 +291,17 @@ remove_confirm_repo (GsReposDialog *dialog, GsApp *repo)
        GtkStyleContext *context;
 
        remove_data = g_slice_new0 (InstallRemoveData);
-       remove_data->action = GS_PLUGIN_ACTION_REMOVE;
        remove_data->repo = g_object_ref (repo);
        remove_data->dialog = g_object_ref (dialog);
 
        if (repo_supports_removal (repo)) {
+               remove_data->action = GS_PLUGIN_ACTION_REMOVE_REPO;
                /* TRANSLATORS: this is a prompt message, and '%s' is a
                 * repository name, e.g. 'GNOME Nightly' */
                title = g_strdup_printf (_("Remove ā€œ%sā€?"),
                                         gs_app_get_name (repo));
        } else {
+               remove_data->action = GS_PLUGIN_ACTION_DISABLE_REPO;
                /* TRANSLATORS: this is a prompt message, and '%s' is a
                 * repository name, e.g. 'GNOME Nightly' */
                title = g_strdup_printf (_("Disable ā€œ%sā€?"),
diff --git a/src/gs-shell.c b/src/gs-shell.c
index 15d06a5b6..539b0b060 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -1992,12 +1992,16 @@ gs_shell_show_event (GsShell *shell, GsPluginEvent *event)
        case GS_PLUGIN_ACTION_DOWNLOAD:
                return gs_shell_show_event_refresh (shell, event);
        case GS_PLUGIN_ACTION_INSTALL:
+       case GS_PLUGIN_ACTION_INSTALL_REPO:
+       case GS_PLUGIN_ACTION_ENABLE_REPO:
                return gs_shell_show_event_install (shell, event);
        case GS_PLUGIN_ACTION_UPDATE:
                return gs_shell_show_event_update (shell, event);
        case GS_PLUGIN_ACTION_UPGRADE_DOWNLOAD:
                return gs_shell_show_event_upgrade (shell, event);
        case GS_PLUGIN_ACTION_REMOVE:
+       case GS_PLUGIN_ACTION_REMOVE_REPO:
+       case GS_PLUGIN_ACTION_DISABLE_REPO:
                return gs_shell_show_event_remove (shell, event);
        case GS_PLUGIN_ACTION_LAUNCH:
                return gs_shell_show_event_launch (shell, event);


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