summaryrefslogtreecommitdiffstats
path: root/lib/gs-plugin-job.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/gs-plugin-job.c502
1 files changed, 502 insertions, 0 deletions
diff --git a/lib/gs-plugin-job.c b/lib/gs-plugin-job.c
new file mode 100644
index 0000000..a40980f
--- /dev/null
+++ b/lib/gs-plugin-job.c
@@ -0,0 +1,502 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2017-2018 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2018 Kalev Lember <klember@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include "gs-enums.h"
+#include "gs-plugin-private.h"
+#include "gs-plugin-job-private.h"
+
+typedef struct
+{
+ GsPluginRefineFlags refine_flags;
+ GsAppListFilterFlags dedupe_flags;
+ gboolean interactive;
+ gboolean propagate_error;
+ guint max_results;
+ GsPlugin *plugin;
+ GsPluginAction action;
+ GsAppListSortFunc sort_func;
+ gpointer sort_func_data;
+ gchar *search;
+ GsApp *app;
+ GsAppList *list;
+ GFile *file;
+ gint64 time_created;
+} GsPluginJobPrivate;
+
+enum {
+ PROP_0,
+ PROP_ACTION,
+ PROP_SEARCH,
+ PROP_REFINE_FLAGS,
+ PROP_DEDUPE_FLAGS,
+ PROP_INTERACTIVE,
+ PROP_APP,
+ PROP_LIST,
+ PROP_FILE,
+ PROP_MAX_RESULTS,
+ PROP_PROPAGATE_ERROR,
+ PROP_LAST
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (GsPluginJob, gs_plugin_job, G_TYPE_OBJECT)
+
+gchar *
+gs_plugin_job_to_string (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ GString *str = g_string_new (NULL);
+ gint64 time_now = g_get_monotonic_time ();
+ g_string_append_printf (str, "running %s",
+ gs_plugin_action_to_string (priv->action));
+ if (priv->plugin != NULL) {
+ g_string_append_printf (str, " on plugin=%s",
+ gs_plugin_get_name (priv->plugin));
+ }
+ if (priv->dedupe_flags > 0)
+ g_string_append_printf (str, " with dedupe-flags=%" G_GUINT64_FORMAT, priv->dedupe_flags);
+ if (priv->refine_flags > 0) {
+ g_autofree gchar *tmp = gs_plugin_refine_flags_to_string (priv->refine_flags);
+ g_string_append_printf (str, " with refine-flags=%s", tmp);
+ }
+ if (priv->interactive)
+ g_string_append_printf (str, " with interactive=True");
+ if (priv->propagate_error)
+ g_string_append_printf (str, " with propagate-error=True");
+
+ if (priv->max_results > 0)
+ g_string_append_printf (str, " with max-results=%u", priv->max_results);
+ if (priv->search != NULL) {
+ g_string_append_printf (str, " with search=%s",
+ priv->search);
+ }
+ if (priv->file != NULL) {
+ g_autofree gchar *path = g_file_get_path (priv->file);
+ g_string_append_printf (str, " with file=%s", path);
+ }
+ if (priv->list != NULL && gs_app_list_length (priv->list) > 0) {
+ g_autofree const gchar **unique_ids = NULL;
+ g_autofree gchar *unique_ids_str = NULL;
+ unique_ids = g_new0 (const gchar *, gs_app_list_length (priv->list) + 1);
+ for (guint i = 0; i < gs_app_list_length (priv->list); i++) {
+ GsApp *app = gs_app_list_index (priv->list, i);
+ unique_ids[i] = gs_app_get_unique_id (app);
+ }
+ unique_ids_str = g_strjoinv (",", (gchar**) unique_ids);
+ g_string_append_printf (str, " on apps %s", unique_ids_str);
+ }
+ if (time_now - priv->time_created > 1000) {
+ g_string_append_printf (str, ", elapsed time since creation %" G_GINT64_FORMAT "ms",
+ (time_now - priv->time_created) / 1000);
+ }
+ return g_string_free (str, FALSE);
+}
+
+void
+gs_plugin_job_set_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->refine_flags = refine_flags;
+}
+
+void
+gs_plugin_job_set_dedupe_flags (GsPluginJob *self, GsAppListFilterFlags dedupe_flags)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->dedupe_flags = dedupe_flags;
+}
+
+GsPluginRefineFlags
+gs_plugin_job_get_refine_flags (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), GS_PLUGIN_REFINE_FLAGS_NONE);
+ return priv->refine_flags;
+}
+
+GsAppListFilterFlags
+gs_plugin_job_get_dedupe_flags (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), GS_APP_LIST_FILTER_FLAG_NONE);
+ return priv->dedupe_flags;
+}
+
+gboolean
+gs_plugin_job_has_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), FALSE);
+ return (priv->refine_flags & refine_flags) > 0;
+}
+
+void
+gs_plugin_job_add_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->refine_flags |= refine_flags;
+}
+
+void
+gs_plugin_job_remove_refine_flags (GsPluginJob *self, GsPluginRefineFlags refine_flags)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->refine_flags &= ~refine_flags;
+}
+
+void
+gs_plugin_job_set_interactive (GsPluginJob *self, gboolean interactive)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->interactive = interactive;
+}
+
+gboolean
+gs_plugin_job_get_interactive (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), FALSE);
+ return priv->interactive;
+}
+
+void
+gs_plugin_job_set_propagate_error (GsPluginJob *self, gboolean propagate_error)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->propagate_error = propagate_error;
+}
+
+gboolean
+gs_plugin_job_get_propagate_error (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), FALSE);
+ return priv->propagate_error;
+}
+
+void
+gs_plugin_job_set_max_results (GsPluginJob *self, guint max_results)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->max_results = max_results;
+}
+
+guint
+gs_plugin_job_get_max_results (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), 0);
+ return priv->max_results;
+}
+
+void
+gs_plugin_job_set_action (GsPluginJob *self, GsPluginAction action)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->action = action;
+}
+
+GsPluginAction
+gs_plugin_job_get_action (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), GS_PLUGIN_ACTION_UNKNOWN);
+ return priv->action;
+}
+
+void
+gs_plugin_job_set_sort_func (GsPluginJob *self, GsAppListSortFunc sort_func, gpointer user_data)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ priv->sort_func = sort_func;
+ priv->sort_func_data = user_data;
+}
+
+GsAppListSortFunc
+gs_plugin_job_get_sort_func (GsPluginJob *self, gpointer *user_data_out)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ if (user_data_out != NULL)
+ *user_data_out = priv->sort_func_data;
+ return priv->sort_func;
+}
+
+void
+gs_plugin_job_set_search (GsPluginJob *self, const gchar *search)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_free (priv->search);
+ priv->search = g_strdup (search);
+}
+
+const gchar *
+gs_plugin_job_get_search (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return priv->search;
+}
+
+void
+gs_plugin_job_set_app (GsPluginJob *self, GsApp *app)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&priv->app, app);
+
+ /* ensure we can always operate on a list object */
+ if (priv->list != NULL && app != NULL && gs_app_list_length (priv->list) == 0)
+ gs_app_list_add (priv->list, priv->app);
+}
+
+GsApp *
+gs_plugin_job_get_app (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return priv->app;
+}
+
+void
+gs_plugin_job_set_list (GsPluginJob *self, GsAppList *list)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ if (list == NULL)
+ g_warning ("trying to set list to NULL, not a good idea");
+ g_set_object (&priv->list, list);
+}
+
+GsAppList *
+gs_plugin_job_get_list (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return priv->list;
+}
+
+void
+gs_plugin_job_set_file (GsPluginJob *self, GFile *file)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&priv->file, file);
+}
+
+GFile *
+gs_plugin_job_get_file (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return priv->file;
+}
+
+void
+gs_plugin_job_set_plugin (GsPluginJob *self, GsPlugin *plugin)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_if_fail (GS_IS_PLUGIN_JOB (self));
+ g_set_object (&priv->plugin, plugin);
+}
+
+GsPlugin *
+gs_plugin_job_get_plugin (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_PLUGIN_JOB (self), NULL);
+ return priv->plugin;
+}
+
+static void
+gs_plugin_job_get_property (GObject *obj, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GsPluginJob *self = GS_PLUGIN_JOB (obj);
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+
+ switch (prop_id) {
+ case PROP_ACTION:
+ g_value_set_enum (value, priv->action);
+ break;
+ case PROP_REFINE_FLAGS:
+ g_value_set_flags (value, priv->refine_flags);
+ break;
+ case PROP_DEDUPE_FLAGS:
+ g_value_set_flags (value, priv->dedupe_flags);
+ break;
+ case PROP_INTERACTIVE:
+ g_value_set_boolean (value, priv->interactive);
+ break;
+ case PROP_SEARCH:
+ g_value_set_string (value, priv->search);
+ break;
+ case PROP_APP:
+ g_value_set_object (value, priv->app);
+ break;
+ case PROP_LIST:
+ g_value_set_object (value, priv->list);
+ break;
+ case PROP_FILE:
+ g_value_set_object (value, priv->file);
+ break;
+ case PROP_MAX_RESULTS:
+ g_value_set_uint (value, priv->max_results);
+ break;
+ case PROP_PROPAGATE_ERROR:
+ g_value_set_boolean (value, priv->propagate_error);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_plugin_job_set_property (GObject *obj, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GsPluginJob *self = GS_PLUGIN_JOB (obj);
+
+ switch (prop_id) {
+ case PROP_ACTION:
+ gs_plugin_job_set_action (self, g_value_get_enum (value));
+ break;
+ case PROP_REFINE_FLAGS:
+ gs_plugin_job_set_refine_flags (self, g_value_get_flags (value));
+ break;
+ case PROP_DEDUPE_FLAGS:
+ gs_plugin_job_set_dedupe_flags (self, g_value_get_flags (value));
+ break;
+ case PROP_INTERACTIVE:
+ gs_plugin_job_set_interactive (self, g_value_get_boolean (value));
+ break;
+ case PROP_SEARCH:
+ gs_plugin_job_set_search (self, g_value_get_string (value));
+ break;
+ case PROP_APP:
+ gs_plugin_job_set_app (self, g_value_get_object (value));
+ break;
+ case PROP_LIST:
+ gs_plugin_job_set_list (self, g_value_get_object (value));
+ break;
+ case PROP_FILE:
+ gs_plugin_job_set_file (self, g_value_get_object (value));
+ break;
+ case PROP_MAX_RESULTS:
+ gs_plugin_job_set_max_results (self, g_value_get_uint (value));
+ break;
+ case PROP_PROPAGATE_ERROR:
+ gs_plugin_job_set_propagate_error (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_plugin_job_finalize (GObject *obj)
+{
+ GsPluginJob *self = GS_PLUGIN_JOB (obj);
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+
+ g_free (priv->search);
+ g_clear_object (&priv->app);
+ g_clear_object (&priv->list);
+ g_clear_object (&priv->file);
+ g_clear_object (&priv->plugin);
+
+ G_OBJECT_CLASS (gs_plugin_job_parent_class)->finalize (obj);
+}
+
+static void
+gs_plugin_job_class_init (GsPluginJobClass *klass)
+{
+ GParamSpec *pspec;
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gs_plugin_job_finalize;
+ object_class->get_property = gs_plugin_job_get_property;
+ object_class->set_property = gs_plugin_job_set_property;
+
+ pspec = g_param_spec_enum ("action", NULL, NULL,
+ GS_TYPE_PLUGIN_ACTION, GS_PLUGIN_ACTION_UNKNOWN,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_ACTION, pspec);
+
+ pspec = g_param_spec_flags ("refine-flags", NULL, NULL,
+ GS_TYPE_PLUGIN_REFINE_FLAGS, GS_PLUGIN_REFINE_FLAGS_NONE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_REFINE_FLAGS, pspec);
+
+ pspec = g_param_spec_flags ("dedupe-flags", NULL, NULL,
+ GS_TYPE_APP_LIST_FILTER_FLAGS, GS_APP_LIST_FILTER_FLAG_NONE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_DEDUPE_FLAGS, pspec);
+
+ pspec = g_param_spec_boolean ("interactive", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_property (object_class, PROP_INTERACTIVE, pspec);
+
+ pspec = g_param_spec_string ("search", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_SEARCH, pspec);
+
+ pspec = g_param_spec_object ("app", NULL, NULL,
+ GS_TYPE_APP,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_APP, pspec);
+
+ pspec = g_param_spec_object ("list", NULL, NULL,
+ GS_TYPE_APP_LIST,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_LIST, pspec);
+
+ pspec = g_param_spec_object ("file", NULL, NULL,
+ G_TYPE_FILE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_FILE, pspec);
+
+ pspec = g_param_spec_uint ("max-results", NULL, NULL,
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_MAX_RESULTS, pspec);
+
+ pspec = g_param_spec_boolean ("propagate-error", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (object_class, PROP_PROPAGATE_ERROR, pspec);
+}
+
+static void
+gs_plugin_job_init (GsPluginJob *self)
+{
+ GsPluginJobPrivate *priv = gs_plugin_job_get_instance_private (self);
+
+ priv->refine_flags = GS_PLUGIN_REFINE_FLAGS_NONE;
+ priv->dedupe_flags = GS_APP_LIST_FILTER_FLAG_KEY_ID |
+ GS_APP_LIST_FILTER_FLAG_KEY_SOURCE |
+ GS_APP_LIST_FILTER_FLAG_KEY_VERSION;
+ priv->list = gs_app_list_new ();
+ priv->time_created = g_get_monotonic_time ();
+}