diff options
Diffstat (limited to '')
-rw-r--r-- | lib/gs-cmd.c | 847 |
1 files changed, 847 insertions, 0 deletions
diff --git a/lib/gs-cmd.c b/lib/gs-cmd.c new file mode 100644 index 0000000..895e1b8 --- /dev/null +++ b/lib/gs-cmd.c @@ -0,0 +1,847 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * vi:set noexpandtab tabstop=8 shiftwidth=8: + * + * Copyright (C) 2013-2017 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2014-2015 Kalev Lember <klember@redhat.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "config.h" + +#include <glib/gi18n.h> +#include <gtk/gtk.h> +#include <locale.h> + +#include "gnome-software-private.h" + +#include "gs-debug.h" + +typedef struct { + GsPluginLoader *plugin_loader; + guint64 refine_flags; + guint max_results; + gboolean interactive; +} GsCmdSelf; + +static void +gs_cmd_show_results_apps (GsAppList *list) +{ + for (guint j = 0; j < gs_app_list_length (list); j++) { + GsApp *app = gs_app_list_index (list, j); + GsAppList *related = gs_app_get_related (app); + g_autofree gchar *tmp = gs_app_to_string (app); + g_print ("%s\n", tmp); + for (guint i = 0; i < gs_app_list_length (related); i++) { + g_autofree gchar *tmp_rel = NULL; + GsApp *app_rel = GS_APP (gs_app_list_index (related, i)); + tmp_rel = gs_app_to_string (app_rel); + g_print ("\t%s\n", tmp_rel); + } + } +} + +static gchar * +gs_cmd_pad_spaces (const gchar *text, guint length) +{ + gsize i; + GString *str; + str = g_string_sized_new (length + 1); + g_string_append (str, text); + for (i = strlen (text); i < length; i++) + g_string_append_c (str, ' '); + return g_string_free (str, FALSE); +} + +static void +gs_cmd_show_results_categories (GPtrArray *list) +{ + for (guint i = 0; i < list->len; i++) { + GsCategory *cat = GS_CATEGORY (g_ptr_array_index (list, i)); + GsCategory *parent = gs_category_get_parent (cat); + g_autofree gchar *tmp = NULL; + if (parent != NULL){ + g_autofree gchar *id = NULL; + id = g_strdup_printf ("%s/%s [%u]", + gs_category_get_id (parent), + gs_category_get_id (cat), + gs_category_get_size (cat)); + tmp = gs_cmd_pad_spaces (id, 32); + g_print ("%s : %s\n", + tmp, gs_category_get_name (cat)); + } else { + GPtrArray *subcats = gs_category_get_children (cat); + tmp = gs_cmd_pad_spaces (gs_category_get_id (cat), 32); + g_print ("%s : %s\n", + tmp, gs_category_get_name (cat)); + gs_cmd_show_results_categories (subcats); + } + } +} + +static GsPluginRefineFlags +gs_cmd_refine_flag_from_string (const gchar *flag, GError **error) +{ + if (g_strcmp0 (flag, "all") == 0) + return G_MAXINT32; + if (g_strcmp0 (flag, "license") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_LICENSE; + if (g_strcmp0 (flag, "url") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_URL; + if (g_strcmp0 (flag, "description") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_DESCRIPTION; + if (g_strcmp0 (flag, "size") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_SIZE; + if (g_strcmp0 (flag, "rating") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_RATING; + if (g_strcmp0 (flag, "version") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_VERSION; + if (g_strcmp0 (flag, "history") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_HISTORY; + if (g_strcmp0 (flag, "setup-action") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION; + if (g_strcmp0 (flag, "update-details") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPDATE_DETAILS; + if (g_strcmp0 (flag, "origin") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN; + if (g_strcmp0 (flag, "related") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_RELATED; + if (g_strcmp0 (flag, "menu-path") == 0) + /* no longer supported by itself; categories are largely equivalent */ + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_CATEGORIES; + if (g_strcmp0 (flag, "upgrade-removed") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPGRADE_REMOVED; + if (g_strcmp0 (flag, "provenance") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROVENANCE; + if (g_strcmp0 (flag, "reviews") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEWS; + if (g_strcmp0 (flag, "review-ratings") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_REVIEW_RATINGS; + if (g_strcmp0 (flag, "key-colors") == 0) + /* no longer supported by itself; derived automatically from the icon */ + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON; + if (g_strcmp0 (flag, "icon") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON; + if (g_strcmp0 (flag, "permissions") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_PERMISSIONS; + if (g_strcmp0 (flag, "origin-hostname") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN_HOSTNAME; + if (g_strcmp0 (flag, "origin-ui") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_ORIGIN_UI; + if (g_strcmp0 (flag, "runtime") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_RUNTIME; + if (g_strcmp0 (flag, "categories") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_CATEGORIES; + if (g_strcmp0 (flag, "project-group") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_PROJECT_GROUP; + if (g_strcmp0 (flag, "developer-name") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_DEVELOPER_NAME; + if (g_strcmp0 (flag, "kudos") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_KUDOS; + if (g_strcmp0 (flag, "content-rating") == 0) + return GS_PLUGIN_REFINE_FLAGS_REQUIRE_CONTENT_RATING; + g_set_error (error, + GS_PLUGIN_ERROR, + GS_PLUGIN_ERROR_NOT_SUPPORTED, + "GsPluginRefineFlag '%s' not recognised", flag); + return 0; +} + +static guint64 +gs_cmd_parse_refine_flags (const gchar *extra, GError **error) +{ + GsPluginRefineFlags tmp; + guint i; + guint64 refine_flags = GS_PLUGIN_REFINE_FLAGS_NONE; + g_auto(GStrv) split = NULL; + + if (extra == NULL) + return GS_PLUGIN_REFINE_FLAGS_NONE; + + split = g_strsplit (extra, ",", -1); + for (i = 0; split[i] != NULL; i++) { + tmp = gs_cmd_refine_flag_from_string (split[i], error); + if (tmp == 0) + return G_MAXUINT64; + refine_flags |= tmp; + } + return refine_flags; +} + +static guint +gs_cmd_prompt_for_number (guint maxnum) +{ + gint retval; + guint answer = 0; + + do { + char buffer[64]; + + /* swallow the \n at end of line too */ + if (!fgets (buffer, sizeof (buffer), stdin)) + break; + if (strlen (buffer) == sizeof (buffer) - 1) + continue; + + /* get a number */ + retval = sscanf (buffer, "%u", &answer); + + /* positive */ + if (retval == 1 && answer > 0 && answer <= maxnum) + break; + + /* TRANSLATORS: the user isn't reading the question */ + g_print (_("Please enter a number from 1 to %u: "), maxnum); + } while (TRUE); + return answer; +} + +static gboolean +gs_cmd_action_exec (GsCmdSelf *self, GsPluginAction action, const gchar *name, GError **error) +{ + g_autoptr(GsApp) app = NULL; + g_autoptr(GsAppList) list = NULL; + g_autoptr(GsAppList) list_filtered = NULL; + g_autoptr(GsAppQuery) query = NULL; + g_autoptr(GsPluginJob) plugin_job2 = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + gboolean show_installed = TRUE; + const gchar * const keywords[] = { name, NULL }; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + /* ensure set */ + self->refine_flags |= GS_PLUGIN_REFINE_FLAGS_REQUIRE_ICON; + self->refine_flags |= GS_PLUGIN_REFINE_FLAGS_REQUIRE_SETUP_ACTION; + + /* do search */ + query = gs_app_query_new ("keywords", keywords, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT, + "sort-func", gs_utils_app_sort_match_value, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, NULL, error); + if (list == NULL) + return FALSE; + if (gs_app_list_length (list) == 0) { + g_set_error (error, + GS_PLUGIN_ERROR, + GS_PLUGIN_ERROR_FAILED, + "no components matched '%s'", + name); + return FALSE; + } + + /* filter */ + if (action == GS_PLUGIN_ACTION_INSTALL) + show_installed = FALSE; + list_filtered = gs_app_list_new (); + for (guint i = 0; i < gs_app_list_length (list); i++) { + GsApp *app_tmp = gs_app_list_index (list, i); + if (gs_app_is_installed (app_tmp) == show_installed) + gs_app_list_add (list_filtered, app_tmp); + } + + /* nothing */ + if (gs_app_list_length (list_filtered) == 0) { + g_set_error (error, + GS_PLUGIN_ERROR, + GS_PLUGIN_ERROR_FAILED, + "no components were in the correct state for '%s %s'", + gs_plugin_action_to_string (action), name); + return FALSE; + } + + /* get one GsApp */ + if (gs_app_list_length (list_filtered) == 1) { + app = g_object_ref (gs_app_list_index (list_filtered, 0)); + } else { + guint idx; + /* TRANSLATORS: asking the user to choose an app from a list */ + g_print ("%s\n", _("Choose an application:")); + for (guint i = 0; i < gs_app_list_length (list_filtered); i++) { + GsApp *app_tmp = gs_app_list_index (list_filtered, i); + g_print ("%u.\t%s\n", + i + 1, + gs_app_get_unique_id (app_tmp)); + } + idx = gs_cmd_prompt_for_number (gs_app_list_length (list_filtered)); + app = g_object_ref (gs_app_list_index (list_filtered, idx - 1)); + } + + /* install */ + plugin_job2 = gs_plugin_job_newv (action, + "app", app, + "interactive", self->interactive, + NULL); + return gs_plugin_loader_job_action (self->plugin_loader, plugin_job2, + NULL, error); +} + +static void +gs_cmd_self_free (GsCmdSelf *self) +{ + if (self->plugin_loader != NULL) + g_object_unref (self->plugin_loader); + g_free (self); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GsCmdSelf, gs_cmd_self_free) + +static gint +app_sort_kind_cb (GsApp *app1, GsApp *app2, gpointer user_data) +{ + if (gs_app_get_kind (app1) == AS_COMPONENT_KIND_DESKTOP_APP) + return -1; + if (gs_app_get_kind (app2) == AS_COMPONENT_KIND_DESKTOP_APP) + return 1; + return 0; +} + +int +main (int argc, char **argv) +{ + g_autoptr(GOptionContext) context = NULL; + gboolean prefer_local = FALSE; + gboolean ret; + gboolean show_results = FALSE; + gboolean verbose = FALSE; + gint i; + guint64 cache_age_secs = 0; + gint repeat = 1; + g_auto(GStrv) plugin_blocklist = NULL; + g_auto(GStrv) plugin_allowlist = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GsAppList) list = NULL; + g_autoptr(GPtrArray) categories = NULL; + g_autoptr(GsDebug) debug = gs_debug_new_from_environment (); + g_autofree gchar *plugin_blocklist_str = NULL; + g_autofree gchar *plugin_allowlist_str = NULL; + g_autofree gchar *refine_flags_str = NULL; + g_autoptr(GsApp) app = NULL; + g_autoptr(GFile) file = NULL; + g_autoptr(GsCmdSelf) self = g_new0 (GsCmdSelf, 1); + const GOptionEntry options[] = { + { "show-results", '\0', 0, G_OPTION_ARG_NONE, &show_results, + "Show the results for the action", NULL }, + { "refine-flags", '\0', 0, G_OPTION_ARG_STRING, &refine_flags_str, + "Set any refine flags required for the action", NULL }, + { "repeat", '\0', 0, G_OPTION_ARG_INT, &repeat, + "Repeat the action this number of times", NULL }, + { "cache-age", '\0', 0, G_OPTION_ARG_INT64, &cache_age_secs, + "Use this maximum cache age in seconds", NULL }, + { "max-results", '\0', 0, G_OPTION_ARG_INT, &self->max_results, + "Return a maximum number of results", NULL }, + { "prefer-local", '\0', 0, G_OPTION_ARG_NONE, &prefer_local, + "Prefer local file sources to AppStream", NULL }, + { "plugin-blocklist", '\0', 0, G_OPTION_ARG_STRING, &plugin_blocklist_str, + "Do not load specific plugins", NULL }, + { "plugin-allowlist", '\0', 0, G_OPTION_ARG_STRING, &plugin_allowlist_str, + "Only load specific plugins", NULL }, + { "verbose", '\0', 0, G_OPTION_ARG_NONE, &verbose, + "Show verbose debugging information", NULL }, + { "interactive", 'i', 0, G_OPTION_ARG_NONE, &self->interactive, + "Allow interactive authentication", NULL }, + { NULL} + }; + + setlocale (LC_ALL, ""); + + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + + gtk_init (); + + context = g_option_context_new (NULL); + g_option_context_set_summary (context, "GNOME Software Test Program"); + g_option_context_add_main_entries (context, options, NULL); + ret = g_option_context_parse (context, &argc, &argv, &error); + if (!ret) { + g_print ("Failed to parse options: %s\n", error->message); + return EXIT_FAILURE; + } + gs_debug_set_verbose (debug, verbose); + + /* prefer local sources */ + if (prefer_local) + g_setenv ("GNOME_SOFTWARE_PREFER_LOCAL", "true", TRUE); + + /* parse any refine flags */ + self->refine_flags = gs_cmd_parse_refine_flags (refine_flags_str, &error); + if (self->refine_flags == G_MAXUINT64) { + g_print ("Flag unknown: %s\n", error->message); + return EXIT_FAILURE; + } + + /* load plugins */ + self->plugin_loader = gs_plugin_loader_new (NULL, NULL); + if (g_file_test (LOCALPLUGINDIR, G_FILE_TEST_EXISTS)) + gs_plugin_loader_add_location (self->plugin_loader, LOCALPLUGINDIR); + if (plugin_allowlist_str != NULL) + plugin_allowlist = g_strsplit (plugin_allowlist_str, ",", -1); + if (plugin_blocklist_str != NULL) + plugin_blocklist = g_strsplit (plugin_blocklist_str, ",", -1); + ret = gs_plugin_loader_setup (self->plugin_loader, + (const gchar * const *) plugin_allowlist, + (const gchar * const *) plugin_blocklist, + NULL, + &error); + if (!ret) { + g_print ("Failed to setup plugins: %s\n", error->message); + return EXIT_FAILURE; + } + gs_plugin_loader_dump_state (self->plugin_loader); + + /* ensure that at least some metadata of any age is present, and also + * spin up the plugins enough as to prime caches */ + if (g_getenv ("GS_CMD_NO_INITIAL_REFRESH") == NULL) { + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginRefreshMetadataFlags refresh_metadata_flags = GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE; + + if (self->interactive) + refresh_metadata_flags |= GS_PLUGIN_REFRESH_METADATA_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_refresh_metadata_new (G_MAXUINT64, refresh_metadata_flags); + ret = gs_plugin_loader_job_action (self->plugin_loader, plugin_job, + NULL, &error); + if (!ret) { + g_print ("Failed to refresh plugins: %s\n", error->message); + return EXIT_FAILURE; + } + } + + /* do action */ + if (argc == 2 && g_strcmp0 (argv[1], "installed") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsAppQuery) query = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("is-installed", GS_APP_QUERY_TRISTATE_TRUE, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 3 && g_strcmp0 (argv[1], "search") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsAppQuery) query = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + const gchar *keywords[2] = { argv[2], NULL }; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("keywords", keywords, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT, + "sort-func", gs_utils_app_sort_match_value, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 3 && g_strcmp0 (argv[1], "get-alternates") == 0) { + app = gs_app_new (argv[2]); + gs_app_add_quirk (app, GS_APP_QUIRK_IS_WILDCARD); + for (i = 0; i < repeat; i++) { + g_autoptr(GsAppQuery) query = NULL; + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("alternate-of", app, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "dedupe-flags", GS_PLUGIN_JOB_DEDUPE_FLAGS_DEFAULT, + "sort-func", gs_utils_app_sort_priority, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 4 && g_strcmp0 (argv[1], "action") == 0) { + GsPluginAction action = gs_plugin_action_from_string (argv[2]); + if (action == GS_PLUGIN_ACTION_UNKNOWN) { + ret = FALSE; + g_set_error (&error, + GS_PLUGIN_ERROR, + GS_PLUGIN_ERROR_FAILED, + "Did not recognise action '%s'", argv[2]); + } else { + ret = gs_cmd_action_exec (self, action, argv[3], &error); + } + } else if (argc == 3 && g_strcmp0 (argv[1], "action-upgrade-download") == 0) { + g_autoptr(GsPluginJob) plugin_job = NULL; + app = gs_app_new (argv[2]); + gs_app_set_kind (app, AS_COMPONENT_KIND_OPERATING_SYSTEM); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_UPGRADE_DOWNLOAD, + "app", app, + "interactive", self->interactive, + NULL); + ret = gs_plugin_loader_job_action (self->plugin_loader, plugin_job, + NULL, &error); + if (ret) + gs_app_list_add (list, app); + } else if (argc == 3 && g_strcmp0 (argv[1], "refine") == 0) { + app = gs_app_new (argv[2]); + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + plugin_job = gs_plugin_job_refine_new_for_app (app, self->refine_flags); + ret = gs_plugin_loader_job_action (self->plugin_loader, plugin_job, + NULL, &error); + if (!ret) + break; + } + list = gs_app_list_new (); + gs_app_list_add (list, app); + } else if (argc == 3 && g_strcmp0 (argv[1], "launch") == 0) { + app = gs_app_new (argv[2]); + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_LAUNCH, + "app", app, + "interactive", self->interactive, + NULL); + ret = gs_plugin_loader_job_action (self->plugin_loader, plugin_job, + NULL, &error); + if (!ret) + break; + } + } else if (argc == 3 && g_strcmp0 (argv[1], "filename-to-app") == 0) { + g_autoptr(GsPluginJob) plugin_job = NULL; + file = g_file_new_for_path (argv[2]); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_FILE_TO_APP, + "file", file, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "interactive", self->interactive, + NULL); + app = gs_plugin_loader_job_process_app (self->plugin_loader, plugin_job, NULL, &error); + if (app == NULL) { + ret = FALSE; + } else { + list = gs_app_list_new (); + gs_app_list_add (list, app); + } + } else if (argc == 3 && g_strcmp0 (argv[1], "url-to-app") == 0) { + g_autoptr(GsPluginJob) plugin_job = NULL; + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_URL_TO_APP, + "search", argv[2], + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "interactive", self->interactive, + NULL); + app = gs_plugin_loader_job_process_app (self->plugin_loader, plugin_job, + NULL, &error); + if (app == NULL) { + ret = FALSE; + } else { + list = gs_app_list_new (); + gs_app_list_add (list, app); + } + } else if (argc == 2 && g_strcmp0 (argv[1], "updates") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + if (list != NULL) + g_object_unref (list); + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_UPDATES, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "interactive", self->interactive, + NULL); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 2 && g_strcmp0 (argv[1], "upgrades") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginListDistroUpgradesFlags upgrades_flags = GS_PLUGIN_LIST_DISTRO_UPGRADES_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + if (self->interactive) + upgrades_flags |= GS_PLUGIN_LIST_DISTRO_UPGRADES_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_distro_upgrades_new (upgrades_flags, self->refine_flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 2 && g_strcmp0 (argv[1], "sources") == 0) { + g_autoptr(GsPluginJob) plugin_job = NULL; + plugin_job = gs_plugin_job_newv (GS_PLUGIN_ACTION_GET_SOURCES, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "interactive", self->interactive, + NULL); + list = gs_plugin_loader_job_process (self->plugin_loader, + plugin_job, + NULL, + &error); + if (list == NULL) + ret = FALSE; + } else if (argc == 2 && g_strcmp0 (argv[1], "popular") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + g_autoptr(GsAppQuery) query = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("is-curated", GS_APP_QUERY_TRISTATE_TRUE, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "sort-func", app_sort_kind_cb, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 2 && g_strcmp0 (argv[1], "featured") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + g_autoptr(GsAppQuery) query = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("is-featured", GS_APP_QUERY_TRISTATE_TRUE, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 3 && g_strcmp0 (argv[1], "deployment-featured") == 0) { + g_auto(GStrv) split = g_strsplit (argv[2], ",", -1); + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + g_autoptr(GsAppQuery) query = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("deployment-featured", split, + "refine-flags", self->refine_flags, + "dedupe-flags", GS_APP_LIST_FILTER_FLAG_KEY_ID, + "max-results", self->max_results, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 2 && g_strcmp0 (argv[1], "recent") == 0) { + if (cache_age_secs == 0) + cache_age_secs = 60 * 60 * 24 * 60; + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + g_autoptr(GDateTime) now = NULL; + g_autoptr(GDateTime) released_since = NULL; + g_autoptr(GsAppQuery) query = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + now = g_date_time_new_now_local (); + released_since = g_date_time_add_seconds (now, -cache_age_secs); + query = gs_app_query_new ("released-since", released_since, + "refine-flags", self->refine_flags, + "dedupe-flags", GS_APP_LIST_FILTER_FLAG_KEY_ID, + "max-results", self->max_results, + "sort-func", app_sort_kind_cb, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, + NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc == 2 && g_strcmp0 (argv[1], "get-categories") == 0) { + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginRefineCategoriesFlags flags = GS_PLUGIN_REFINE_CATEGORIES_FLAGS_SIZE; + + if (categories != NULL) + g_ptr_array_unref (categories); + + if (self->interactive) + flags |= GS_PLUGIN_REFINE_CATEGORIES_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_categories_new (flags); + if (!gs_plugin_loader_job_action (self->plugin_loader, plugin_job, NULL, &error)) { + ret = FALSE; + break; + } + + categories = g_ptr_array_ref (gs_plugin_job_list_categories_get_result_list (GS_PLUGIN_JOB_LIST_CATEGORIES (plugin_job))); + } + } else if (argc == 3 && g_strcmp0 (argv[1], "get-category-apps") == 0) { + g_autoptr(GsCategory) category_owned = NULL; + GsCategory *category = NULL; + g_auto(GStrv) split = NULL; + GsCategoryManager *manager = gs_plugin_loader_get_category_manager (self->plugin_loader); + + split = g_strsplit (argv[2], "/", 2); + if (g_strv_length (split) == 1) { + category_owned = gs_category_manager_lookup (manager, split[0]); + category = category_owned; + } else { + g_autoptr(GsCategory) parent = gs_category_manager_lookup (manager, split[0]); + if (parent != NULL) + category = gs_category_find_child (parent, split[1]); + } + + if (category == NULL) { + g_printerr ("Error: Could not find category ā%sā\n", argv[2]); + return EXIT_FAILURE; + } + + for (i = 0; i < repeat; i++) { + g_autoptr(GsPluginJob) plugin_job = NULL; + g_autoptr(GsAppQuery) query = NULL; + GsPluginListAppsFlags flags = GS_PLUGIN_LIST_APPS_FLAGS_NONE; + + if (list != NULL) + g_object_unref (list); + + query = gs_app_query_new ("category", category, + "refine-flags", self->refine_flags, + "max-results", self->max_results, + "sort-func", gs_utils_app_sort_name, + NULL); + + if (self->interactive) + flags |= GS_PLUGIN_LIST_APPS_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_list_apps_new (query, flags); + list = gs_plugin_loader_job_process (self->plugin_loader, plugin_job, NULL, &error); + if (list == NULL) { + ret = FALSE; + break; + } + } + } else if (argc >= 2 && g_strcmp0 (argv[1], "refresh") == 0) { + g_autoptr(GsPluginJob) plugin_job = NULL; + GsPluginRefreshMetadataFlags refresh_metadata_flags = GS_PLUGIN_REFRESH_METADATA_FLAGS_NONE; + + if (self->interactive) + refresh_metadata_flags |= GS_PLUGIN_REFRESH_METADATA_FLAGS_INTERACTIVE; + + plugin_job = gs_plugin_job_refresh_metadata_new (cache_age_secs, refresh_metadata_flags); + ret = gs_plugin_loader_job_action (self->plugin_loader, plugin_job, + NULL, &error); + } else if (argc >= 1 && g_strcmp0 (argv[1], "user-hash") == 0) { + g_autofree gchar *user_hash = gs_utils_get_user_hash (&error); + if (user_hash == NULL) { + ret = FALSE; + } else { + g_print ("%s\n", user_hash); + ret = TRUE; + } + } else { + ret = FALSE; + g_set_error_literal (&error, + GS_PLUGIN_ERROR, + GS_PLUGIN_ERROR_FAILED, + "Did not recognise option, use 'installed', " + "'updates', 'popular', 'get-categories', " + "'get-category-apps', 'get-alternates', 'filename-to-app', " + "'action install', 'action remove', " + "'sources', 'refresh', 'launch' or 'search'"); + } + if (!ret) { + g_print ("Failed: %s\n", error->message); + return EXIT_FAILURE; + } + + if (show_results) { + if (list != NULL) + gs_cmd_show_results_apps (list); + if (categories != NULL) + gs_cmd_show_results_categories (categories); + } + return EXIT_SUCCESS; +} |