[gnome-builder] pkcon: add IdePkconTransfer



commit dd6997fec6057f202c4cafd9a76855eb7f185596
Author: Christian Hergert <chergert redhat com>
Date:   Fri Mar 10 00:28:35 2017 -0800

    pkcon: add IdePkconTransfer
    
    This is a new transfer that can perform installations of packages using
    the pkcon command on the host. Such is useful for installing packages
    like "flatpak-builder".

 libide/Makefile.am                    |    2 +
 libide/ide.h                          |    1 +
 libide/transfers/ide-pkcon-transfer.c |  278 +++++++++++++++++++++++++++++++++
 libide/transfers/ide-pkcon-transfer.h |   34 ++++
 po/POTFILES.in                        |    1 +
 5 files changed, 316 insertions(+), 0 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 845d4be..c25561d 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -151,6 +151,7 @@ libide_1_0_la_public_headers =                                              \
        template/ide-template-base.h                                        \
        template/ide-template-provider.h                                    \
        threading/ide-thread-pool.h                                         \
+       transfers/ide-pkcon-transfer.h                                      \
        transfers/ide-transfer-manager.h                                    \
        transfers/ide-transfer-row.h                                        \
        transfers/ide-transfer.h                                            \
@@ -331,6 +332,7 @@ libide_1_0_la_public_sources =                                              \
        template/ide-template-base.c                                        \
        template/ide-template-provider.c                                    \
        threading/ide-thread-pool.c                                         \
+       transfers/ide-pkcon-transfer.c                                      \
        transfers/ide-transfer-manager.c                                    \
        transfers/ide-transfer-row.c                                        \
        transfers/ide-transfer.c                                            \
diff --git a/libide/ide.h b/libide/ide.h
index 45ffea0..38b2c9f 100644
--- a/libide/ide.h
+++ b/libide/ide.h
@@ -142,6 +142,7 @@ G_BEGIN_DECLS
 #include "template/ide-project-template.h"
 #include "template/ide-template-provider.h"
 #include "threading/ide-thread-pool.h"
+#include "transfers/ide-pkcon-transfer.h"
 #include "transfers/ide-transfer.h"
 #include "transfers/ide-transfer-button.h"
 #include "transfers/ide-transfer-manager.h"
diff --git a/libide/transfers/ide-pkcon-transfer.c b/libide/transfers/ide-pkcon-transfer.c
new file mode 100644
index 0000000..b4b755a
--- /dev/null
+++ b/libide/transfers/ide-pkcon-transfer.c
@@ -0,0 +1,278 @@
+/* ide-pkcon-transfer.c
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-pkcon-transfer"
+
+#include <glib/gi18n.h>
+
+#include "ide-debug.h"
+
+#include "subprocess/ide-subprocess.h"
+#include "subprocess/ide-subprocess-launcher.h"
+#include "transfers/ide-pkcon-transfer.h"
+
+struct _IdePkconTransfer
+{
+  IdeTransfer   parent;
+  gchar       **packages;
+  gchar        *status;
+};
+
+enum {
+  PROP_0,
+  PROP_PACKAGES,
+  N_PROPS
+};
+
+G_DEFINE_TYPE (IdePkconTransfer, ide_pkcon_transfer, IDE_TYPE_TRANSFER)
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+ide_pkcon_transfer_update_title (IdePkconTransfer *self)
+{
+  g_autofree gchar *title = NULL;
+  guint count;
+
+  g_assert (IDE_IS_PKCON_TRANSFER (self));
+
+  count = g_strv_length (self->packages);
+  title = g_strdup_printf (ngettext ("Installing %u package", "Installing %u packages", count), count);
+  ide_transfer_set_title (IDE_TRANSFER (self), title);
+}
+
+static void
+ide_pkcon_transfer_wait_check_cb (GObject      *object,
+                                  GAsyncResult *result,
+                                  gpointer      user_data)
+{
+  IdeSubprocess *subprocess = (IdeSubprocess *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (IDE_IS_SUBPROCESS (subprocess));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  if (!ide_subprocess_wait_check_finish (subprocess, result, &error))
+    g_task_return_error (task, g_steal_pointer (&error));
+  else
+    g_task_return_boolean (task, TRUE);
+}
+
+static void
+ide_pkcon_transfer_read_line_cb (GObject      *object,
+                                 GAsyncResult *result,
+                                 gpointer      user_data)
+{
+  GDataInputStream *stream = (GDataInputStream *)object;
+  g_autoptr(IdePkconTransfer) self = user_data;
+  g_autofree gchar *line = NULL;
+  g_auto(GStrv) parts = NULL;
+  gsize len;
+
+  g_assert (G_IS_DATA_INPUT_STREAM (stream));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_PKCON_TRANSFER (self));
+
+  if (!(line = g_data_input_stream_read_line_finish_utf8 (stream, result, &len, NULL)))
+    return;
+
+  parts = g_strsplit (line, ":", 2);
+
+  if (parts[0]) g_strstrip (parts[0]);
+  if (parts[1]) g_strstrip (parts[1]);
+
+  if (g_strcmp0 (parts[0], "Status") == 0)
+    ide_transfer_set_status (IDE_TRANSFER (self), parts[1]);
+  else if (g_strcmp0 (parts[0], "Percentage") == 0 && parts[1])
+    ide_transfer_set_progress (IDE_TRANSFER (self), g_strtod (parts[1], NULL) / 100.0);
+
+  g_data_input_stream_read_line_async (stream,
+                                       G_PRIORITY_DEFAULT,
+                                       NULL,
+                                       ide_pkcon_transfer_read_line_cb,
+                                       g_object_ref (self));
+}
+
+static void
+ide_pkcon_transfer_execute_async (IdeTransfer         *transfer,
+                                  GCancellable        *cancellable,
+                                  GAsyncReadyCallback  callback,
+                                  gpointer             user_data)
+{
+  IdePkconTransfer *self = (IdePkconTransfer *)transfer;
+  g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+  g_autoptr(IdeSubprocess) subprocess = NULL;
+  g_autoptr(GDataInputStream) data_stream = NULL;
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(GError) error = NULL;
+  GInputStream *stdout_stream;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_TRANSFER (transfer));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_pkcon_transfer_execute_async);
+
+  if (self->packages == NULL || !self->packages[0])
+    {
+      g_task_return_boolean (task, TRUE);
+      IDE_EXIT;
+    }
+
+  launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
+  ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
+  ide_subprocess_launcher_push_argv (launcher, "pkcon");
+  ide_subprocess_launcher_push_argv (launcher, "install");
+  ide_subprocess_launcher_push_argv (launcher, "-y");
+  ide_subprocess_launcher_push_argv (launcher, "-p");
+
+  for (guint i = 0; self->packages[i]; i++)
+    ide_subprocess_launcher_push_argv (launcher, self->packages[i]);
+
+  subprocess = ide_subprocess_launcher_spawn (launcher, cancellable, &error);
+
+  if (subprocess == NULL)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      IDE_EXIT;
+    }
+
+  stdout_stream = ide_subprocess_get_stdout_pipe (subprocess);
+  data_stream = g_data_input_stream_new (stdout_stream);
+
+  g_data_input_stream_read_line_async (data_stream,
+                                       G_PRIORITY_DEFAULT,
+                                       cancellable,
+                                       ide_pkcon_transfer_read_line_cb,
+                                       g_object_ref (self));
+
+  ide_subprocess_wait_check_async (subprocess,
+                                   cancellable,
+                                   ide_pkcon_transfer_wait_check_cb,
+                                   g_steal_pointer (&task));
+
+  IDE_EXIT;
+}
+
+static gboolean
+ide_pkcon_transfer_execute_finish (IdeTransfer   *transfer,
+                                   GAsyncResult  *result,
+                                   GError       **error)
+{
+  gboolean ret;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_TRANSFER (transfer));
+  g_assert (G_IS_TASK (result));
+
+  ret = g_task_propagate_boolean (G_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+ide_pkcon_transfer_finalize (GObject *object)
+{
+  IdePkconTransfer *self = (IdePkconTransfer *)object;
+
+  g_clear_pointer (&self->packages, g_strfreev);
+  g_clear_pointer (&self->status, g_free);
+
+  G_OBJECT_CLASS (ide_pkcon_transfer_parent_class)->finalize (object);
+}
+
+static void
+ide_pkcon_transfer_get_property (GObject    *object,
+                                 guint       prop_id,
+                                 GValue     *value,
+                                 GParamSpec *pspec)
+{
+  IdePkconTransfer *self = IDE_PKCON_TRANSFER (object);
+
+  switch (prop_id)
+    {
+    case PROP_PACKAGES:
+      g_value_set_boxed (value, self->packages);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_pkcon_transfer_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  IdePkconTransfer *self = IDE_PKCON_TRANSFER (object);
+
+  switch (prop_id)
+    {
+    case PROP_PACKAGES:
+      self->packages = g_value_dup_boxed (value);
+      ide_pkcon_transfer_update_title (self);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_pkcon_transfer_class_init (IdePkconTransferClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  IdeTransferClass *transfer_class = IDE_TRANSFER_CLASS (klass);
+
+  object_class->finalize = ide_pkcon_transfer_finalize;
+  object_class->get_property = ide_pkcon_transfer_get_property;
+  object_class->set_property = ide_pkcon_transfer_set_property;
+
+  transfer_class->execute_async = ide_pkcon_transfer_execute_async;
+  transfer_class->execute_finish = ide_pkcon_transfer_execute_finish;
+
+  properties [PROP_PACKAGES] =
+    g_param_spec_boxed ("packages",
+                        "Packages",
+                        "The package names to be installed",
+                        G_TYPE_STRV,
+                        (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+ide_pkcon_transfer_init (IdePkconTransfer *self)
+{
+  ide_transfer_set_icon_name (IDE_TRANSFER (self), "system-software-install-symbolic");
+}
+
+IdePkconTransfer *
+ide_pkcon_transfer_new (const gchar * const *packages)
+{
+  return g_object_new (IDE_TYPE_PKCON_TRANSFER,
+                       "packages", packages,
+                       NULL);
+}
diff --git a/libide/transfers/ide-pkcon-transfer.h b/libide/transfers/ide-pkcon-transfer.h
new file mode 100644
index 0000000..83b4bbd
--- /dev/null
+++ b/libide/transfers/ide-pkcon-transfer.h
@@ -0,0 +1,34 @@
+/* ide-pkcon-transfer.h
+ *
+ * Copyright (C) 2017 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_PKCON_TRANSFER_H
+#define IDE_PKCON_TRANSFER_H
+
+#include "ide-transfer.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_PKCON_TRANSFER (ide_pkcon_transfer_get_type())
+
+G_DECLARE_FINAL_TYPE (IdePkconTransfer, ide_pkcon_transfer, IDE, PKCON_TRANSFER, IdeTransfer)
+
+IdePkconTransfer *ide_pkcon_transfer_new (const gchar * const *packages);
+
+G_END_DECLS
+
+#endif /* IDE_PKCON_TRANSFER_H */
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 075e964..0c27672 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -94,6 +94,7 @@ libide/snippets/ide-source-snippet.c
 libide/snippets/ide-source-snippet-completion-provider.c
 libide/snippets/ide-source-snippets-manager.c
 libide/sourceview/ide-source-view.c
+libide/transfers/ide-pkcon-transfer.c
 libide/transfers/ide-transfers-button.ui
 libide/util/ide-file-manager.c
 libide/util/ide-uri.c


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