[gnome-software/wip/temp/ubuntu-xenial-rebased-corrected: 24/331] Add an apt plugin that works with aptdaemon
- From: William Hua <williamhua src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-software/wip/temp/ubuntu-xenial-rebased-corrected: 24/331] Add an apt plugin that works with aptdaemon
- Date: Wed, 4 May 2016 14:00:31 +0000 (UTC)
commit 519dcf033c2a9994cc56ad32ea3dd0e7f35c77fa
Author: Robert Ancell <robert ancell canonical com>
Date: Thu Feb 4 14:51:21 2016 +1300
Add an apt plugin that works with aptdaemon
src/plugins/Makefile.am | 1 +
src/plugins/gs-plugin-apt.c | 372 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 373 insertions(+), 0 deletions(-)
---
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 8b020b3..c8a224b 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -28,6 +28,7 @@ AM_CPPFLAGS = \
plugindir = $(libdir)/gs-plugins-${GS_PLUGIN_API_VERSION}
plugin_LTLIBRARIES = \
+ libgs_plugin_apt.la \
libgs_plugin_appstream.la \
libgs_plugin_dummy.la \
libgs_plugin_hardcoded-featured.la \
diff --git a/src/plugins/gs-plugin-apt.c b/src/plugins/gs-plugin-apt.c
new file mode 100644
index 0000000..be523a8
--- /dev/null
+++ b/src/plugins/gs-plugin-apt.c
@@ -0,0 +1,372 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2016 Canonical Ltd
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <gs-plugin.h>
+
+struct GsPluginPrivate {
+};
+
+const gchar *
+gs_plugin_get_name (void)
+{
+ return "apt";
+}
+
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+ plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+}
+
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+}
+
+static GsApp *
+find_app (GList **list, const gchar *source)
+{
+ GList *link;
+
+ for (link = *list; link; link = link->next) {
+ GsApp *app = GS_APP (link->data);
+ if (g_strcmp0 (gs_app_get_source_default (app), source) == 0)
+ return app;
+ }
+
+ return NULL;
+}
+
+gboolean
+gs_plugin_refine (GsPlugin *plugin,
+ GList **list,
+ GsPluginRefineFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GList *link;
+ GPtrArray *argv_array;
+ gboolean known_apps = FALSE;
+ g_autofree gchar *output = NULL, **argv = NULL;
+ gint exit_status;
+ gchar **lines;
+ gint i;
+ gboolean is_installed;
+ GsApp *app = NULL;
+ const gchar *package_prefix = "Package: ";
+ const gchar *status_prefix = "Status: ";
+ const gchar *version_prefix = "Version: ";
+
+ g_printerr ("APT: gs_plugin_refine\n");
+
+ // Get the information from the cache
+ argv_array = g_ptr_array_new ();
+ g_ptr_array_add (argv_array, (gpointer) "apt-cache");
+ g_ptr_array_add (argv_array, (gpointer) "show");
+ for (link = *list; link; link = link->next) {
+ const gchar *source;
+
+ app = GS_APP (link->data);
+
+ source = gs_app_get_source_default (app);
+ if (!source)
+ continue;
+
+ // If state already known then nothing to add
+ //if (gs_app_get_state (app) != AS_APP_STATE_UNKNOWN)
+ // continue;
+
+ known_apps = TRUE;
+ g_ptr_array_add (argv_array, (gpointer) source);
+ }
+ g_ptr_array_add (argv_array, NULL);
+ argv = (gchar **) g_ptr_array_free (argv_array, FALSE);
+ if (!known_apps)
+ return TRUE;
+ if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &output, NULL, &exit_status,
error))
+ return FALSE;
+ if (exit_status != EXIT_SUCCESS) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ "apt-cache show returned status %d", exit_status);
+ return FALSE;
+ }
+
+ // Parse information
+ lines = g_strsplit (output, "\n", -1);
+ is_installed = FALSE;
+ for (app = NULL, i = 0; lines[i]; i++) {
+ //g_printerr ("'%s'\n", lines[i]);
+ if (g_str_has_prefix (lines[i], package_prefix)) {
+ app = find_app (list, lines[i] + strlen (package_prefix));
+ if (app && gs_app_get_state (app) == AS_APP_STATE_UNKNOWN)
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+ is_installed = FALSE;
+ }
+
+ // Skip other fields until we find an app we know
+ if (!app)
+ continue;
+
+ if (g_str_has_prefix (lines[i], status_prefix)) {
+ if (g_str_has_suffix (lines[i] + strlen (status_prefix), " installed")) {
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+ is_installed = TRUE;
+ }
+ } else if (g_str_has_prefix (lines[i], version_prefix)) {
+ if (is_installed) {
+ g_printerr ("%s update %s\n", gs_app_get_id (app), lines[i] + strlen
(version_prefix));
+ gs_app_set_version (app, lines[i] + strlen (version_prefix));
+ } else {// FIXME: Could be multiple versions available, could be versions older than
installed
+ g_printerr ("%s update %s\n", gs_app_get_id (app), lines[i] + strlen
(version_prefix));
+ //gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+ gs_app_set_update_version (app, lines[i] + strlen (version_prefix));
+ }
+ }
+ }
+
+ g_strfreev (lines);
+
+ return TRUE;
+}
+
+gboolean
+gs_plugin_add_installed (GsPlugin *plugin,
+ GList **list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_autofree gchar *output = NULL;
+ gint exit_status;
+ gchar **lines = NULL;
+ int i;
+
+ g_printerr ("APT: gs_plugin_add_installed\n");
+
+ if (!g_spawn_command_line_sync ("dpkg --get-selections", &output, NULL, &exit_status, error))
+ return FALSE;
+ if (exit_status != EXIT_SUCCESS) {
+ g_set_error (error,
+ GS_PLUGIN_ERROR,
+ GS_PLUGIN_ERROR_FAILED,
+ "dpkg --get-selections returned status %d", exit_status);
+ return FALSE;
+ }
+
+ lines = g_strsplit (output, "\n", -1);
+ for (i = 0; lines[i]; i++) {
+ g_autoptr(GsApp) app = NULL;
+ gchar *id, *status, *c;
+
+ // Line is the form <name>\t<status> - find the status and only use installed packages
+ status = strrchr (lines[i], '\t');
+ if (!status)
+ continue;
+ status++;
+ if (strcmp (status, "install") != 0)
+ continue;
+
+ // Split out name
+ c = strchr (lines[i], '\t');
+ *c = '\0';
+ id = lines[i];
+
+ app = gs_app_new (id);
+ gs_app_add_source (app, id);
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+ gs_plugin_add_app (list, app);
+ }
+ g_strfreev (lines);
+
+ return TRUE;
+}
+
+static void
+transaction_property_changed_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GsApp *app = user_data;
+ const gchar *name;
+ g_autoptr(GVariant) value = NULL;
+
+ g_variant_get (parameters, "(&sv)", &name, &value);
+ if (strcmp (name, "Progress") == 0)
+ gs_app_set_progress (app, g_variant_get_int32 (value));
+}
+
+static void
+transaction_finished_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ GMainLoop *loop = user_data;
+ const gchar *result;
+
+ g_variant_get (parameters, "(&s)", &result);
+ g_printerr ("FINISHED %s\n", result);
+ // FIXME: Check result is "exit-success"
+
+ g_main_loop_quit (loop);
+}
+
+static gboolean
+aptd_transaction (const gchar *method, GsApp *app, GError **error)
+{
+ g_autoptr(GDBusConnection) conn = NULL;
+ g_autoptr(GVariant) result = NULL;
+ GVariantBuilder builder;
+ gchar *transaction_path = NULL;
+ g_autoptr(GMainLoop) loop = NULL;
+
+ conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
+ if (conn == NULL)
+ return FALSE;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("as")),
+ g_variant_builder_add (&builder, "s", gs_app_get_source_default (app));
+ result = g_dbus_connection_call_sync (conn,
+ "org.debian.apt",
+ "/org/debian/apt",
+ "org.debian.apt",
+ method,
+ g_variant_new ("(as)", &builder),
+ G_VARIANT_TYPE ("(s)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+ if (!result)
+ return FALSE;
+ g_variant_get (result, "(s)", &transaction_path);
+ g_variant_unref (result);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ // FIXME: Keep handlers to remove later
+ g_dbus_connection_signal_subscribe (conn,
+ "org.debian.apt",
+ "org.debian.apt.transaction",
+ "PropertyChanged",
+ transaction_path,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ transaction_property_changed_cb,
+ app,
+ NULL);
+ g_dbus_connection_signal_subscribe (conn,
+ "org.debian.apt",
+ "org.debian.apt.transaction",
+ "Finished",
+ transaction_path,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ transaction_finished_cb,
+ loop,
+ NULL);
+ result = g_dbus_connection_call_sync (conn,
+ "org.debian.apt",
+ transaction_path,
+ "org.debian.apt.transaction",
+ "Run",
+ g_variant_new ("()"),
+ G_VARIANT_TYPE (""),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ error);
+ if (!result)
+ return FALSE;
+
+ g_main_loop_run (loop);
+
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+
+ return TRUE;
+}
+
+gboolean
+gs_plugin_app_install (GsPlugin *plugin,
+ GsApp *app,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_printerr ("APT: gs_plugin_app_install\n");
+
+ if (!gs_app_get_source_default (app))
+ return TRUE;
+
+ gs_app_set_state (app, AS_APP_STATE_INSTALLING);
+ if (aptd_transaction ("InstallPackages", app, error))
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+ else {
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gs_plugin_app_remove (GsPlugin *plugin,
+ GsApp *app,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_printerr ("APT: gs_plugin_app_remove\n");
+
+ if (!gs_app_get_source_default (app))
+ return TRUE;
+
+ gs_app_set_state (app, AS_APP_STATE_REMOVING);
+ if (aptd_transaction ("RemovePackages", app, error))
+ gs_app_set_state (app, AS_APP_STATE_AVAILABLE);
+ else {
+ gs_app_set_state (app, AS_APP_STATE_INSTALLED);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gs_plugin_refresh (GsPlugin *plugin,
+ guint cache_age,
+ GsPluginRefreshFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_printerr ("APT: gs_plugin_refresh\n");
+ return TRUE;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]