[gnome-builder/wip/chergert/git-oop: 16/34] implement reading of configuration data



commit 96bca3814e89e8deda1a58adc5cdb3c162fa781a
Author: Christian Hergert <chergert redhat com>
Date:   Wed Mar 20 18:00:53 2019 -0700

    implement reading of configuration data

 src/plugins/git/gbp-git-client.c     |  23 ++++++++
 src/plugins/git/gbp-git-client.h     |   4 ++
 src/plugins/git/gbp-git-vcs-config.c | 111 +++++++++++++----------------------
 src/plugins/git/gbp-git-vcs-config.h |   2 +-
 src/plugins/git/gbp-git.c            | 101 +++++++++++++++++++++++++++++++
 src/plugins/git/gbp-git.h            |   8 +++
 src/plugins/git/gnome-builder-git.c  |  55 +++++++++++++++++
 7 files changed, 233 insertions(+), 71 deletions(-)
---
diff --git a/src/plugins/git/gbp-git-client.c b/src/plugins/git/gbp-git-client.c
index 945b643e7..96afe5538 100644
--- a/src/plugins/git/gbp-git-client.c
+++ b/src/plugins/git/gbp-git-client.c
@@ -933,3 +933,26 @@ gbp_git_client_update_config_finish (GbpGitClient  *self,
 
   return ide_task_propagate_boolean (IDE_TASK (result), error);
 }
+
+GVariant *
+gbp_git_client_read_config (GbpGitClient  *self,
+                            const gchar   *key,
+                            GCancellable  *cancellable,
+                            GError       **error)
+{
+  g_autoptr(GVariant) reply = NULL;
+
+  g_return_val_if_fail (GBP_IS_GIT_CLIENT (self), FALSE);
+  g_return_val_if_fail (key != NULL, FALSE);
+  g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
+
+  if (!gbp_git_client_call (self,
+                            "git/readConfig",
+                            g_variant_new_string (key),
+                            cancellable,
+                            &reply,
+                            error))
+    return NULL;
+
+  return g_steal_pointer (&reply);
+}
diff --git a/src/plugins/git/gbp-git-client.h b/src/plugins/git/gbp-git-client.h
index 6fe777d6f..48b151770 100644
--- a/src/plugins/git/gbp-git-client.h
+++ b/src/plugins/git/gbp-git-client.h
@@ -99,6 +99,10 @@ void          gbp_git_client_update_submodules_async  (GbpGitClient           *s
 gboolean      gbp_git_client_update_submodules_finish (GbpGitClient           *self,
                                                        GAsyncResult           *result,
                                                        GError                **error);
+GVariant     *gbp_git_client_read_config              (GbpGitClient           *self,
+                                                       const gchar            *key,
+                                                       GCancellable           *cancellable,
+                                                       GError                **error);
 gboolean      gbp_git_client_update_config            (GbpGitClient           *self,
                                                        gboolean                global,
                                                        const gchar            *key,
diff --git a/src/plugins/git/gbp-git-vcs-config.c b/src/plugins/git/gbp-git-vcs-config.c
index cf8a20153..823b17917 100644
--- a/src/plugins/git/gbp-git-vcs-config.c
+++ b/src/plugins/git/gbp-git-vcs-config.c
@@ -22,22 +22,20 @@
 
 #include "config.h"
 
-#include <libgit2-glib/ggit.h>
 #include <libide-vcs.h>
 
+#include "gbp-git-client.h"
 #include "gbp-git-vcs-config.h"
 
 struct _GbpGitVcsConfig
 {
-  GObject     parent_instance;
-
-  GgitConfig *config;
+  IdeObject parent_instance;
 };
 
 static void vcs_config_init (IdeVcsConfigInterface *iface);
 
-G_DEFINE_TYPE_EXTENDED (GbpGitVcsConfig, gbp_git_vcs_config, G_TYPE_OBJECT, 0,
-                        G_IMPLEMENT_INTERFACE (IDE_TYPE_VCS_CONFIG, vcs_config_init))
+G_DEFINE_TYPE_WITH_CODE (GbpGitVcsConfig, gbp_git_vcs_config, IDE_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (IDE_TYPE_VCS_CONFIG, vcs_config_init))
 
 GbpGitVcsConfig *
 gbp_git_vcs_config_new (void)
@@ -46,36 +44,44 @@ gbp_git_vcs_config_new (void)
 }
 
 static void
-gbp_git_vcs_config_get_string (GgitConfig  *config,
-                               const gchar *key,
-                               GValue      *value,
-                               GError     **error)
+gbp_git_vcs_config_get_string (GbpGitClient  *client,
+                               const gchar   *key,
+                               GValue        *value,
+                               GError       **error)
 {
-  const gchar *str;
+  g_autoptr(GVariant) v = NULL;
 
-  g_assert (GGIT_IS_CONFIG (config));
+  g_assert (GBP_IS_GIT_CLIENT (client));
   g_assert (key != NULL);
 
-  str = ggit_config_get_string (config, key, error);
+  /*
+   * Not ideal to communicate accross processes synchronously here,
+   * but it's fine for now until we have async APIs for this (or implement
+   * configuration reading in process with caching.
+   */
 
-  g_value_set_string (value, str);
+  if ((v = gbp_git_client_read_config (client, key, NULL, error)))
+    {
+      g_value_init (value, G_TYPE_STRING);
+      g_value_set_string (value, g_variant_get_string (v, NULL));
+    }
 }
 
 static void
-gbp_git_vcs_config_set_string (GgitConfig   *config,
-                               const gchar  *key,
-                               const GValue *value,
-                               GError      **error)
+gbp_git_vcs_config_set_string (GbpGitClient  *client,
+                               const gchar   *key,
+                               const GValue  *value,
+                               GError       **error)
 {
-  const gchar *str;
+  g_autoptr(GVariant) v = NULL;
 
-  g_assert (GGIT_IS_CONFIG (config));
+  g_assert (GBP_IS_GIT_CLIENT (client));
   g_assert (key != NULL);
 
-  str = g_value_get_string (value);
+  if (G_VALUE_HOLDS_STRING (value))
+    v = g_variant_take_ref (g_variant_new_string (g_value_get_string (value)));
 
-  if (str != NULL)
-    ggit_config_set_string (config, key, str, error);
+  gbp_git_client_update_config (client, TRUE, key, v, NULL, error);
 }
 
 static void
@@ -83,25 +89,22 @@ gbp_git_vcs_config_get_config (IdeVcsConfig    *self,
                                IdeVcsConfigType type,
                                GValue          *value)
 {
-  g_autoptr(GgitConfig) config = NULL;
-  GgitConfig *orig_config;
+  GbpGitClient *client;
+  IdeContext *context;
 
   g_return_if_fail (GBP_IS_GIT_VCS_CONFIG (self));
 
-  orig_config = GBP_GIT_VCS_CONFIG (self)->config;
-  config = ggit_config_snapshot (orig_config, NULL);
-
-  if(config == NULL)
-    return;
+  context = ide_object_get_context (IDE_OBJECT (self));
+  client = gbp_git_client_from_context (context);
 
   switch (type)
     {
     case IDE_VCS_CONFIG_FULL_NAME:
-      gbp_git_vcs_config_get_string (config, "user.name", value, NULL);
+      gbp_git_vcs_config_get_string (client, "user.name", value, NULL);
       break;
 
     case IDE_VCS_CONFIG_EMAIL:
-      gbp_git_vcs_config_get_string (config, "user.email", value, NULL);
+      gbp_git_vcs_config_get_string (client, "user.email", value, NULL);
       break;
 
     default:
@@ -114,20 +117,22 @@ gbp_git_vcs_config_set_config (IdeVcsConfig    *self,
                                IdeVcsConfigType type,
                                const GValue    *value)
 {
-  GgitConfig *config;
+  GbpGitClient *client;
+  IdeContext *context;
 
   g_return_if_fail (GBP_IS_GIT_VCS_CONFIG (self));
 
-  config = GBP_GIT_VCS_CONFIG (self)->config;
+  context = ide_object_get_context (IDE_OBJECT (self));
+  client = gbp_git_client_from_context (context);
 
   switch (type)
     {
     case IDE_VCS_CONFIG_FULL_NAME:
-      gbp_git_vcs_config_set_string (config, "user.name", value, NULL);
+      gbp_git_vcs_config_set_string (client, "user.name", value, NULL);
       break;
 
     case IDE_VCS_CONFIG_EMAIL:
-      gbp_git_vcs_config_set_string (config, "user.email", value, NULL);
+      gbp_git_vcs_config_set_string (client, "user.email", value, NULL);
       break;
 
     default:
@@ -135,36 +140,6 @@ gbp_git_vcs_config_set_config (IdeVcsConfig    *self,
     }
 }
 
-static void
-gbp_git_vcs_config_constructed (GObject *object)
-{
-  GbpGitVcsConfig *self = GBP_GIT_VCS_CONFIG (object);
-
-  g_autoptr(GFile) global_file = NULL;
-
-  if (!(global_file = ggit_config_find_global ()))
-    {
-      g_autofree gchar *path = NULL;
-
-      path = g_build_filename (g_get_home_dir (), ".gitconfig", NULL);
-      global_file = g_file_new_for_path (path);
-    }
-
-  self->config = ggit_config_new_from_file (global_file, NULL);
-
-  G_OBJECT_CLASS (gbp_git_vcs_config_parent_class)->constructed (object);
-}
-
-static void
-gbp_git_vcs_config_finalize (GObject *object)
-{
-  GbpGitVcsConfig *self = GBP_GIT_VCS_CONFIG (object);
-
-  g_object_unref (self->config);
-
-  G_OBJECT_CLASS (gbp_git_vcs_config_parent_class)->finalize (object);
-}
-
 static void
 vcs_config_init (IdeVcsConfigInterface *iface)
 {
@@ -175,10 +150,6 @@ vcs_config_init (IdeVcsConfigInterface *iface)
 static void
 gbp_git_vcs_config_class_init (GbpGitVcsConfigClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->constructed = gbp_git_vcs_config_constructed;
-  object_class->finalize = gbp_git_vcs_config_finalize;
 }
 
 static void
diff --git a/src/plugins/git/gbp-git-vcs-config.h b/src/plugins/git/gbp-git-vcs-config.h
index acc416d03..22d1c7101 100644
--- a/src/plugins/git/gbp-git-vcs-config.h
+++ b/src/plugins/git/gbp-git-vcs-config.h
@@ -26,7 +26,7 @@ G_BEGIN_DECLS
 
 #define GBP_TYPE_GIT_VCS_CONFIG (gbp_git_vcs_config_get_type())
 
-G_DECLARE_FINAL_TYPE (GbpGitVcsConfig, gbp_git_vcs_config, GBP, GIT_VCS_CONFIG, GObject)
+G_DECLARE_FINAL_TYPE (GbpGitVcsConfig, gbp_git_vcs_config, GBP, GIT_VCS_CONFIG, IdeObject)
 
 GbpGitVcsConfig *gbp_git_vcs_config_new (void);
 
diff --git a/src/plugins/git/gbp-git.c b/src/plugins/git/gbp-git.c
index 1ca86c530..82b56068e 100644
--- a/src/plugins/git/gbp-git.c
+++ b/src/plugins/git/gbp-git.c
@@ -603,3 +603,104 @@ gbp_git_update_config_finish (GbpGit        *self,
 
   return g_task_propagate_boolean (G_TASK (result), error);
 }
+
+typedef struct
+{
+  GFile *workdir;
+  gchar *key;
+} ReadConfig;
+
+static void
+read_config_free (ReadConfig *state)
+{
+  g_clear_object (&state->workdir);
+  g_clear_pointer (&state->key, g_free);
+  g_slice_free (ReadConfig, state);
+}
+
+static void
+gbp_git_read_config_worker (GTask        *task,
+                            gpointer      source_object,
+                            gpointer      task_data,
+                            GCancellable *cancellable)
+{
+  ReadConfig *state = task_data;
+  g_autoptr(GgitRepository) repository = NULL;
+  g_autoptr(GgitConfig) config = NULL;
+  g_autoptr(GgitConfig) snapshot = NULL;
+  g_autoptr(GgitConfigEntry) entry = NULL;
+  g_autoptr(GError) error = NULL;
+  const gchar *str;
+
+  g_assert (G_IS_TASK (task));
+  g_assert (GBP_IS_GIT (source_object));
+  g_assert (state != NULL);
+  g_assert (state->key != NULL);
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  if (state->workdir != NULL)
+    {
+      if (!(repository = ggit_repository_open (state->workdir, &error)) ||
+          !(config = ggit_repository_get_config (repository, &error)))
+        {
+          g_task_return_error (task, g_steal_pointer (&error));
+          return;
+        }
+    }
+  else
+    {
+      if (!(config = ggit_config_new_default (&error)))
+        {
+          g_task_return_error (task, g_steal_pointer (&error));
+          return;
+        }
+    }
+
+  if (!(snapshot = ggit_config_snapshot (config, &error)) ||
+      !(entry = ggit_config_get_entry (snapshot, state->key, &error)))
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  if (!(str = ggit_config_entry_get_value (entry)))
+    str = "";
+
+  g_task_return_pointer (task,
+                         g_variant_take_ref (g_variant_new_string (str)),
+                         (GDestroyNotify)g_variant_unref);
+}
+
+void
+gbp_git_read_config_async (GbpGit              *self,
+                           const gchar         *key,
+                           GCancellable        *cancellable,
+                           GAsyncReadyCallback  callback,
+                           gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+  ReadConfig *state;
+
+  g_assert (GBP_IS_GIT (self));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  state = g_slice_new0 (ReadConfig);
+  state->workdir = self->workdir ? g_file_dup (self->workdir) : NULL;
+  state->key = g_strdup (key);
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, gbp_git_read_config_async);
+  g_task_set_task_data (task, state, (GDestroyNotify)read_config_free);
+  g_task_run_in_thread (task, gbp_git_read_config_worker);
+}
+
+GVariant *
+gbp_git_read_config_finish (GbpGit        *self,
+                            GAsyncResult  *result,
+                            GError       **error)
+{
+  g_assert (GBP_IS_GIT (self));
+  g_assert (G_IS_TASK (result));
+
+  return g_task_propagate_pointer (G_TASK (result), error);
+}
diff --git a/src/plugins/git/gbp-git.h b/src/plugins/git/gbp-git.h
index 724ef9e85..63cd0fc70 100644
--- a/src/plugins/git/gbp-git.h
+++ b/src/plugins/git/gbp-git.h
@@ -107,6 +107,14 @@ void       gbp_git_update_submodules_async  (GbpGit                      *self,
 gboolean   gbp_git_update_submodules_finish (GbpGit                      *self,
                                              GAsyncResult                *result,
                                              GError                     **error);
+void       gbp_git_read_config_async        (GbpGit                      *self,
+                                             const gchar                 *key,
+                                             GCancellable                *cancellable,
+                                             GAsyncReadyCallback          callback,
+                                             gpointer                     user_data);
+GVariant  *gbp_git_read_config_finish       (GbpGit                      *self,
+                                             GAsyncResult                *result,
+                                             GError                     **error);
 void       gbp_git_update_config_async      (GbpGit                      *self,
                                              gboolean                     global,
                                              const gchar                 *key,
diff --git a/src/plugins/git/gnome-builder-git.c b/src/plugins/git/gnome-builder-git.c
index 210ddeca2..bca512761 100644
--- a/src/plugins/git/gnome-builder-git.c
+++ b/src/plugins/git/gnome-builder-git.c
@@ -790,6 +790,60 @@ handle_update_config (JsonrpcServer *server,
                                client_op_ref (op));
 }
 
+/* Handle Read Config {{{1 */
+
+static void
+handle_read_config_cb (GObject      *object,
+                       GAsyncResult *result,
+                       gpointer      user_data)
+{
+  GbpGit *git = (GbpGit *)object;
+  g_autoptr(ClientOp) op = user_data;
+  g_autoptr(GVariant) value = NULL;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (GBP_IS_GIT (git));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (op != NULL);
+
+  if (!(value = gbp_git_read_config_finish (git, result, &error)))
+    client_op_error (op, error);
+  else
+    client_op_reply (op, value);
+}
+
+static void
+handle_read_config (JsonrpcServer *server,
+                    JsonrpcClient *client,
+                    const gchar   *method,
+                    GVariant      *id,
+                    GVariant      *params,
+                    GbpGit        *git)
+{
+  g_autoptr(ClientOp) op = NULL;
+  const gchar *key;
+
+  g_assert (JSONRPC_IS_SERVER (server));
+  g_assert (JSONRPC_IS_CLIENT (client));
+  g_assert (g_str_equal (method, "git/readConfig"));
+  g_assert (id != NULL);
+  g_assert (GBP_IS_GIT (git));
+
+  op = client_op_new (client, id);
+
+  if (!JSONRPC_MESSAGE_PARSE (params, "key", JSONRPC_MESSAGE_GET_STRING (&key)))
+    {
+      client_op_bad_params (op);
+      return;
+    }
+
+  gbp_git_read_config_async (git,
+                             key,
+                             op->cancellable,
+                             (GAsyncReadyCallback)handle_read_config_cb,
+                             client_op_ref (op));
+}
+
 /* Main Loop and Setup {{{1 */
 
 gint
@@ -832,6 +886,7 @@ main (gint argc,
 
   ADD_HANDLER ("initialize", handle_initialize);
   ADD_HANDLER ("git/cloneUrl", handle_clone_url);
+  ADD_HANDLER ("git/readConfig", handle_read_config);
   ADD_HANDLER ("git/isIgnored", handle_is_ignored);
   ADD_HANDLER ("git/listRefsByKind", handle_list_refs_by_kind);
   ADD_HANDLER ("git/switchBranch", handle_switch_branch);


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