[gnome-builder/wip/chergert/git-oop: 8/34] wip
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/git-oop: 8/34] wip
- Date: Sat, 23 Mar 2019 00:10:19 +0000 (UTC)
commit d4b1013283bf84fbbc4818445129d2e80b1367e2
Author: Christian Hergert <chergert redhat com>
Date: Wed Mar 20 11:42:23 2019 -0700
wip
src/plugins/git/gbp-git-client.h | 102 ++++++++------
src/plugins/git/gbp-git-remote-callbacks.c | 219 +++++++++++++++--------------
src/plugins/git/gbp-git-remote-callbacks.h | 24 ++--
src/plugins/git/gbp-git.c | 83 +++++++++++
src/plugins/git/gbp-git.h | 88 +++++++-----
src/plugins/git/gnome-builder-git.c | 187 ++++++++++++++++++++++++
6 files changed, 502 insertions(+), 201 deletions(-)
---
diff --git a/src/plugins/git/gbp-git-client.h b/src/plugins/git/gbp-git-client.h
index b96f07840..cb9cd2c53 100644
--- a/src/plugins/git/gbp-git-client.h
+++ b/src/plugins/git/gbp-git-client.h
@@ -35,50 +35,62 @@ typedef enum
G_DECLARE_FINAL_TYPE (GbpGitClient, gbp_git_client, GBP, GIT_CLIENT, IdeObject)
-GbpGitClient *gbp_git_client_from_context (IdeContext *context);
-void gbp_git_client_call_async (GbpGitClient *self,
- const gchar *method,
- GVariant *params,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gbp_git_client_call_finish (GbpGitClient *self,
- GAsyncResult *result,
- GVariant **reply,
- GError **error);
-void gbp_git_client_is_ignored_async (GbpGitClient *self,
- const gchar *path,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gbp_git_client_is_ignored_finish (GbpGitClient *self,
- GAsyncResult *result,
- GError **error);
-void gbp_git_client_list_status_async (GbpGitClient *self,
- const gchar *directory_or_file,
- gboolean include_descendants,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *gbp_git_client_list_status_finish (GbpGitClient *self,
- GAsyncResult *result,
- GError **error);
-void gbp_git_client_list_refs_by_kind_async (GbpGitClient *self,
- GbpGitRefKind kind,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *gbp_git_client_list_refs_by_kind_finish (GbpGitClient *self,
- GAsyncResult *result,
- GError **error);
-void gbp_git_client_switch_branch_async (GbpGitClient *self,
- const gchar *branch_name,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gbp_git_client_switch_branch_finish (GbpGitClient *self,
- GAsyncResult *result,
- gchar **switch_to_directory,
- GError **error);
+GbpGitClient *gbp_git_client_from_context (IdeContext *context);
+void gbp_git_client_call_async (GbpGitClient *self,
+ const gchar *method,
+ GVariant *params,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_client_call_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GVariant **reply,
+ GError **error);
+void gbp_git_client_is_ignored_async (GbpGitClient *self,
+ const gchar *path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_client_is_ignored_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_git_client_list_status_async (GbpGitClient *self,
+ const gchar *directory_or_file,
+ gboolean include_descendants,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GPtrArray *gbp_git_client_list_status_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_git_client_list_refs_by_kind_async (GbpGitClient *self,
+ GbpGitRefKind kind,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GPtrArray *gbp_git_client_list_refs_by_kind_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_git_client_switch_branch_async (GbpGitClient *self,
+ const gchar *branch_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_client_switch_branch_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ gchar **switch_to_directory,
+ GError **error);
+void gbp_git_client_clone_url_async (GbpGitClient *self,
+ const gchar *url,
+ GFile *destination,
+ GFileProgressCallback progress,
+ gpointer progress_data,
+ GDestroyNotify progress_notify,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_client_clone_url_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/plugins/git/gbp-git-remote-callbacks.c b/src/plugins/git/gbp-git-remote-callbacks.c
index 047b9010c..4bdb9b3e7 100644
--- a/src/plugins/git/gbp-git-remote-callbacks.c
+++ b/src/plugins/git/gbp-git-remote-callbacks.c
@@ -1,21 +1,21 @@
-/* gbp-git-remote-callbacks.c
+/* gnome-builder-git.c
*
- * Copyright 2015-2019 Christian Hergert <christian hergert me>
+ * Copyright 2018-2019 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 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.
+ * 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/>.
*
- * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#define G_LOG_DOMAIN "gbp-git-remote-callbacks"
@@ -29,63 +29,47 @@
struct _GbpGitRemoteCallbacks
{
- GgitRemoteCallbacks parent_instance;
+ GgitRemoteCallbacks parent_instance;
- IdeNotification *progress;
- GString *body;
- GgitCredtype tried;
- guint cancelled : 1;
+ GMutex mutex;
+ GString *body;
+ gdouble progress;
+ guint status_source;
+
+ /* bitflags of what we've tried */
+ GgitCredtype tried;
+
+ guint cancelled : 1;
};
G_DEFINE_TYPE (GbpGitRemoteCallbacks, gbp_git_remote_callbacks, GGIT_TYPE_REMOTE_CALLBACKS)
enum {
- PROP_0,
- PROP_PROGRESS,
- LAST_PROP
+ STATUS,
+ N_SIGNALS
};
-static GParamSpec *properties [LAST_PROP];
+static guint signals [N_SIGNALS];
GgitRemoteCallbacks *
-gbp_git_remote_callbacks_new (IdeNotification *progress)
+gbp_git_remote_callbacks_new (void)
{
- g_return_val_if_fail (IDE_IS_NOTIFICATION (progress), NULL);
-
- return g_object_new (GBP_TYPE_GIT_REMOTE_CALLBACKS,
- "progress", progress,
- NULL);
+ return g_object_new (GBP_TYPE_GIT_REMOTE_CALLBACKS, NULL);
}
-/**
- * gbp_git_remote_callbacks_get_progress:
- *
- * Gets the #IdeNotification for the operation.
- *
- * Returns: (transfer none): An #IdeNotification.
- *
- * Since: 3.32
- */
-IdeNotification *
-gbp_git_remote_callbacks_get_progress (GbpGitRemoteCallbacks *self)
+static gboolean
+gbp_git_remote_callbacks_do_emit_status (GbpGitRemoteCallbacks *self)
{
- g_return_val_if_fail (GBP_IS_GIT_REMOTE_CALLBACKS (self), NULL);
+ g_autofree gchar *message = NULL;
+ gdouble progress = 0.0;
- return self->progress;
-}
+ g_assert (GBP_IS_GIT_REMOTE_CALLBACKS (self));
-static void
-gbp_git_remote_callbacks_real_progress (GgitRemoteCallbacks *callbacks,
- const gchar *message)
-{
- GbpGitRemoteCallbacks *self = (GbpGitRemoteCallbacks *)callbacks;
+ g_mutex_lock (&self->mutex);
- g_assert (GBP_IS_GIT_REMOTE_CALLBACKS (self));
+ self->status_source = 0;
- if (self->body == NULL)
- self->body = g_string_new (message);
- else
- g_string_append (self->body, message);
+ progress = self->progress;
if (self->body->len > 1)
{
@@ -100,7 +84,7 @@ gbp_git_remote_callbacks_real_progress (GgitRemoteCallbacks *callbacks,
{
if (*endptr == '\n' || *endptr == '\r')
{
- message = endptr + 1;
+ message = g_strdup (endptr + 1);
break;
}
@@ -108,7 +92,43 @@ gbp_git_remote_callbacks_real_progress (GgitRemoteCallbacks *callbacks,
}
}
- ide_notification_set_body (self->progress, message);
+ g_mutex_unlock (&self->mutex);
+
+ g_signal_emit (self, signals [STATUS], 0, message, progress);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+gbp_git_remote_callbacks_emit_status (GbpGitRemoteCallbacks *self)
+{
+ g_assert (GBP_IS_GIT_REMOTE_CALLBACKS (self));
+
+ g_mutex_lock (&self->mutex);
+ if (self->status_source == 0)
+ self->status_source = g_idle_add_full (G_PRIORITY_HIGH,
+ (GSourceFunc)gbp_git_remote_callbacks_do_emit_status,
+ g_object_ref (self),
+ g_object_unref);
+ g_mutex_unlock (&self->mutex);
+}
+
+static void
+gbp_git_remote_callbacks_real_progress (GgitRemoteCallbacks *callbacks,
+ const gchar *message)
+{
+ GbpGitRemoteCallbacks *self = (GbpGitRemoteCallbacks *)callbacks;
+
+ g_assert (GBP_IS_GIT_REMOTE_CALLBACKS (self));
+
+ g_mutex_lock (&self->mutex);
+ if (self->body == NULL)
+ self->body = g_string_new (message);
+ else
+ g_string_append (self->body, message);
+ g_mutex_unlock (&self->mutex);
+
+ gbp_git_remote_callbacks_emit_status (self);
}
static void
@@ -130,7 +150,11 @@ gbp_git_remote_callbacks_real_transfer_progress (GgitRemoteCallbacks *callbacks
if (total == 0)
return;
- ide_notification_set_progress (self->progress, (gdouble)received / (gdouble)total);
+ g_mutex_lock (&self->mutex);
+ self->progress = (gdouble)received / (gdouble)total;
+ g_mutex_unlock (&self->mutex);
+
+ gbp_git_remote_callbacks_emit_status (self);
}
static GgitCred *
@@ -168,6 +192,9 @@ gbp_git_remote_callbacks_real_credentials (GgitRemoteCallbacks *callbacks,
cred = ggit_cred_ssh_key_from_agent_new (username_from_url, error);
ret = GGIT_CRED (cred);
self->tried |= GGIT_CREDTYPE_SSH_KEY;
+
+ if (ret != NULL)
+ IDE_RETURN (ret);
}
if ((allowed_types & GGIT_CREDTYPE_SSH_INTERACTIVE) != 0)
@@ -177,15 +204,17 @@ gbp_git_remote_callbacks_real_credentials (GgitRemoteCallbacks *callbacks,
cred = ggit_cred_ssh_interactive_new (username_from_url, error);
ret = GGIT_CRED (cred);
self->tried |= GGIT_CREDTYPE_SSH_INTERACTIVE;
+
+ if (ret != NULL)
+ IDE_RETURN (ret);
}
- if (ret == NULL)
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_NOT_SUPPORTED,
- _("Builder failed to provide appropriate credentials when cloning repository."));
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ _("Builder failed to provide appropriate credentials when cloning repository."));
- IDE_RETURN (ret);
+ IDE_RETURN (NULL);
}
static void
@@ -201,46 +230,11 @@ gbp_git_remote_callbacks_finalize (GObject *object)
self->body = NULL;
}
- G_OBJECT_CLASS (gbp_git_remote_callbacks_parent_class)->finalize (object);
-}
-
-static void
-gbp_git_remote_callbacks_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GbpGitRemoteCallbacks *self = GBP_GIT_REMOTE_CALLBACKS (object);
-
- switch (prop_id)
- {
- case PROP_PROGRESS:
- g_value_set_object (value, gbp_git_remote_callbacks_get_progress (self));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-gbp_git_remote_callbacks_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GbpGitRemoteCallbacks *self = GBP_GIT_REMOTE_CALLBACKS (object);
+ g_clear_handle_id (&self->status_source, g_source_remove);
- switch (prop_id)
- {
- case PROP_PROGRESS:
- g_clear_object (&self->progress);
- self->progress = g_value_dup_object (value);
- break;
+ g_mutex_clear (&self->mutex);
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
+ G_OBJECT_CLASS (gbp_git_remote_callbacks_parent_class)->finalize (object);
}
static void
@@ -250,26 +244,37 @@ gbp_git_remote_callbacks_class_init (GbpGitRemoteCallbacksClass *klass)
GgitRemoteCallbacksClass *callbacks_class = GGIT_REMOTE_CALLBACKS_CLASS (klass);
object_class->finalize = gbp_git_remote_callbacks_finalize;
- object_class->get_property = gbp_git_remote_callbacks_get_property;
- object_class->set_property = gbp_git_remote_callbacks_set_property;
callbacks_class->transfer_progress = gbp_git_remote_callbacks_real_transfer_progress;
callbacks_class->progress = gbp_git_remote_callbacks_real_progress;
callbacks_class->credentials = gbp_git_remote_callbacks_real_credentials;
- properties [PROP_PROGRESS] =
- g_param_spec_object ("progress",
- "Progress",
- "An IdeNotification instance containing the operation progress.",
- IDE_TYPE_NOTIFICATION,
- (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_properties (object_class, LAST_PROP, properties);
+ /**
+ * GbpGitRemoteCallbacks::status:
+ * @self: a GbpGitRemoteCallbacks
+ * @message: the status message string
+ * @progress: the progress for the operation
+ *
+ * This signal is emitted when the progress or the status message changes
+ * for the operation.
+ *
+ * Since: 3.34
+ */
+ signals [STATUS] =
+ g_signal_new ("status",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+ G_TYPE_DOUBLE);
}
static void
gbp_git_remote_callbacks_init (GbpGitRemoteCallbacks *self)
{
+ g_mutex_init (&self->mutex);
}
/**
diff --git a/src/plugins/git/gbp-git-remote-callbacks.h b/src/plugins/git/gbp-git-remote-callbacks.h
index 185fb597c..7ddfbb51c 100644
--- a/src/plugins/git/gbp-git-remote-callbacks.h
+++ b/src/plugins/git/gbp-git-remote-callbacks.h
@@ -1,21 +1,21 @@
-/* gbp-git-remote-callbacks.h
+/* gnome-builder-git.c
*
- * Copyright 2015-2019 Christian Hergert <christian hergert me>
+ * Copyright 2018-2019 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 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.
+ * 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/>.
*
- * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
@@ -29,7 +29,7 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (GbpGitRemoteCallbacks, gbp_git_remote_callbacks, GBP, GIT_REMOTE_CALLBACKS,
GgitRemoteCallbacks)
-GgitRemoteCallbacks *gbp_git_remote_callbacks_new (IdeNotification *progress);
+GgitRemoteCallbacks *gbp_git_remote_callbacks_new (void);
gdouble gbp_git_remote_callbacks_get_fraction (GbpGitRemoteCallbacks *self);
IdeNotification *gbp_git_remote_callbacks_get_progress (GbpGitRemoteCallbacks *self);
void gbp_git_remote_callbacks_cancel (GbpGitRemoteCallbacks *self);
diff --git a/src/plugins/git/gbp-git.c b/src/plugins/git/gbp-git.c
index 1ab230ec2..88c4fb1cd 100644
--- a/src/plugins/git/gbp-git.c
+++ b/src/plugins/git/gbp-git.c
@@ -258,3 +258,86 @@ gbp_git_list_status_finish (GbpGit *self,
return g_task_propagate_pointer (G_TASK (result), error);
}
+
+typedef struct
+{
+ gchar *url;
+ GFile *destination;
+ GgitCloneOptions *options;
+} Clone;
+
+static void
+clone_free (Clone *c)
+{
+ g_clear_pointer (&c->url, g_free);
+ g_clear_object (&c->destination);
+ g_clear_object (&c->options);
+ g_slice_free (Clone, c);
+}
+
+static void
+gbp_git_clone_url_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ Clone *state = task_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (GBP_IS_GIT (source_object));
+ g_assert (state != NULL);
+ g_assert (state->url != NULL);
+ g_assert (state->destination != NULL);
+
+ ggit_repository_clone (state->url,
+ state->destination,
+ state->options,
+ &error);
+
+ if (error != NULL)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+gbp_git_clone_url_async (GbpGit *self,
+ const gchar *url,
+ GFile *destination,
+ GgitCloneOptions *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ Clone *c;
+
+ g_assert (GBP_IS_GIT (self));
+ g_assert (url != NULL);
+ g_assert (G_IS_FILE (destination));
+ g_assert (!options || GGIT_IS_CLONE_OPTIONS (options));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ c = g_slice_new0 (Clone);
+ c->url = g_strdup (url);
+ c->destination = g_object_ref (destination);
+ c->options = options ? g_object_ref (options) : NULL;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gbp_git_clone_url_async);
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_task_data (task, c, (GDestroyNotify)clone_free);
+ g_task_run_in_thread (task, gbp_git_clone_url_worker);
+}
+
+gboolean
+gbp_git_clone_url_finish (GbpGit *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_assert (GBP_IS_GIT (self));
+ g_assert (G_IS_TASK (result));
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/src/plugins/git/gbp-git.h b/src/plugins/git/gbp-git.h
index fb9a59276..63133b51e 100644
--- a/src/plugins/git/gbp-git.h
+++ b/src/plugins/git/gbp-git.h
@@ -20,7 +20,7 @@
#pragma once
-#include <gio/gio.h>
+#include <libgit2-glib/ggit.h>
G_BEGIN_DECLS
@@ -46,44 +46,58 @@ typedef struct
guint is_ignored : 1;
} GbpGitFile;
+typedef void (*GbpGitProgress) (const gchar *message,
+ gdouble progress,
+ gpointer user_data);
+
G_DECLARE_FINAL_TYPE (GbpGit, gbp_git, GBP, GIT, GObject)
GbpGit *gbp_git_new (void);
-void gbp_git_set_workdir (GbpGit *self,
- GFile *workdir);
-void gbp_git_is_ignored_async (GbpGit *self,
- const gchar *path,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gbp_git_is_ignored_finish (GbpGit *self,
- GAsyncResult *result,
- GError **error);
-void gbp_git_list_status_async (GbpGit *self,
- const gchar *directory_or_file,
- gboolean include_descendants,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *gbp_git_list_status_finish (GbpGit *self,
- GAsyncResult *result,
- GError **error);
-void gbp_git_list_refs_by_kind_async (GbpGit *self,
- GbpGitRefKind kind,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GPtrArray *gbp_git_list_refs_by_kind_finish (GbpGit *self,
- GAsyncResult *result,
- GError **error);
-void gbp_git_switch_branch_async (GbpGit *self,
- const gchar *branch_name,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean gbp_git_switch_branch_finish (GbpGit *self,
- GAsyncResult *result,
- gchar **switch_to_directory,
- GError **error);
+void gbp_git_set_workdir (GbpGit *self,
+ GFile *workdir);
+void gbp_git_is_ignored_async (GbpGit *self,
+ const gchar *path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_is_ignored_finish (GbpGit *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_git_list_status_async (GbpGit *self,
+ const gchar *directory_or_file,
+ gboolean include_descendants,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GPtrArray *gbp_git_list_status_finish (GbpGit *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_git_list_refs_by_kind_async (GbpGit *self,
+ GbpGitRefKind kind,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GPtrArray *gbp_git_list_refs_by_kind_finish (GbpGit *self,
+ GAsyncResult *result,
+ GError **error);
+void gbp_git_switch_branch_async (GbpGit *self,
+ const gchar *branch_name,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_switch_branch_finish (GbpGit *self,
+ GAsyncResult *result,
+ gchar **switch_to_directory,
+ GError **error);
+void gbp_git_clone_url_async (GbpGit *self,
+ const gchar *url,
+ GFile *destination,
+ GgitCloneOptions *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_clone_url_finish (GbpGit *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/plugins/git/gnome-builder-git.c b/src/plugins/git/gnome-builder-git.c
index c7d024b14..88a4fe735 100644
--- a/src/plugins/git/gnome-builder-git.c
+++ b/src/plugins/git/gnome-builder-git.c
@@ -34,6 +34,7 @@
#include <unistd.h>
#include "gbp-git.h"
+#include "gbp-git-remote-callbacks.h"
static guint in_flight;
static gboolean closing;
@@ -48,6 +49,7 @@ typedef struct
JsonrpcClient *client;
GVariant *id;
GCancellable *cancellable;
+ gchar *token;
GList link;
} ClientOp;
@@ -99,6 +101,7 @@ client_op_unref (ClientOp *op)
g_clear_object (&op->cancellable);
g_clear_object (&op->client);
g_clear_pointer (&op->id, g_variant_unref);
+ g_clear_pointer (&op->token, g_free);
g_queue_unlink (&ops, &op->link);
g_slice_free (ClientOp, op);
@@ -151,6 +154,21 @@ handle_reply_cb (JsonrpcClient *client,
}
}
+static void
+client_op_notify (ClientOp *op,
+ const gchar *method,
+ GVariant *reply)
+{
+ g_assert (op != NULL);
+ g_assert (op->client != NULL);
+
+ jsonrpc_client_send_notification (op->client,
+ method,
+ reply,
+ op->cancellable,
+ NULL);
+}
+
static void
client_op_reply (ClientOp *op,
GVariant *reply)
@@ -166,6 +184,29 @@ client_op_reply (ClientOp *op,
client_op_ref (op));
}
+static void
+progress_cb (goffset current_num_bytes,
+ goffset total_num_bytes,
+ gpointer user_data)
+{
+ ClientOp *op = user_data;
+ g_autoptr(GVariant) reply = NULL;
+ gdouble progress = 0.0;
+
+ g_assert (op != NULL);
+ g_assert (op->client != NULL);
+
+ if (total_num_bytes > 0)
+ progress = (gdouble)current_num_bytes / (gdouble)total_num_bytes;
+
+ reply = JSONRPC_MESSAGE_NEW (
+ "token", JSONRPC_MESSAGE_PUT_STRING (op->token),
+ "progress", JSONRPC_MESSAGE_PUT_DOUBLE (progress)
+ );
+
+ client_op_notify (op, "$/progress", reply);
+}
+
/* Initialize {{{1 */
static void
@@ -487,6 +528,151 @@ handle_list_refs_by_kind (JsonrpcServer *server,
client_op_ref (op));
}
+/* Clone URL {{{1 */
+
+static void
+handle_clone_url_cb (GbpGit *git,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(ClientOp) op = user_data;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (GBP_IS_GIT (git));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (op != NULL);
+
+ if (!gbp_git_clone_url_finish (git, result, &error))
+ client_op_error (op, error);
+ else
+ client_op_reply (op, g_variant_new_boolean (TRUE));
+}
+
+static void
+handle_clone_url_transfer_cb (GbpGitRemoteCallbacks *callbacks,
+ const gchar *message,
+ ClientOp *op)
+{
+ g_autoptr(GVariant) reply = NULL;
+
+ g_assert (GBP_GIT_REMOTE_CALLBACKS (callbacks));
+ g_assert (op != NULL);
+
+ reply = JSONRPC_MESSAGE_NEW (
+ "token", JSONRPC_MESSAGE_PUT_STRING (op->token),
+ "message", JSONRPC_MESSAGE_PUT_STRING (message)
+ );
+
+ client_op_notify (op, "$/progress", reply);
+}
+
+static void
+handle_clone_url_transfer_progress_cb (GbpGitRemoteCallbacks *callbacks,
+ GgitTransferProgress *stats,
+ ClientOp *op)
+{
+ g_autoptr(GVariant) reply = NULL;
+ gdouble total;
+ gdouble received;
+ gdouble progress = 0.0;
+
+ g_assert (GBP_GIT_REMOTE_CALLBACKS (callbacks));
+ g_assert (op != NULL);
+
+ total = ggit_transfer_progress_get_total_objects (stats);
+ received = ggit_transfer_progress_get_received_objects (stats);
+
+ if (total != 0.0)
+ progress = received / total;
+
+ reply = JSONRPC_MESSAGE_NEW (
+ "token", JSONRPC_MESSAGE_PUT_STRING (op->token),
+ "progress", JSONRPC_MESSAGE_PUT_DOUBLE (progress)
+ );
+
+ client_op_notify (op, "$/progress", reply);
+}
+
+static void
+handle_clone_url (JsonrpcServer *server,
+ JsonrpcClient *client,
+ const gchar *method,
+ GVariant *id,
+ GVariant *params,
+ GbpGit *git)
+{
+ g_autoptr(ClientOp) op = NULL;
+ g_autoptr(GFile) destination = NULL;
+ g_autoptr(GgitCloneOptions) options = NULL;
+ g_autoptr(GgitRemoteCallbacks) callbacks = NULL;
+ GgitFetchOptions *fetch_options = NULL;
+ const gchar *url = NULL;
+ const gchar *dest_uri = NULL;
+ const gchar *token = NULL;
+ const gchar *branch = NULL;
+ gboolean r;
+
+ g_assert (JSONRPC_IS_SERVER (server));
+ g_assert (JSONRPC_IS_CLIENT (client));
+ g_assert (g_str_equal (method, "git/cloneUrl"));
+ g_assert (id != NULL);
+ g_assert (GBP_IS_GIT (git));
+
+ op = client_op_new (client, id);
+
+ r = JSONRPC_MESSAGE_PARSE (params,
+ "url", JSONRPC_MESSAGE_GET_STRING (&url),
+ "destination", JSONRPC_MESSAGE_GET_STRING (&dest_uri),
+ "token", JSONRPC_MESSAGE_GET_STRING (&token)
+ );
+
+ JSONRPC_MESSAGE_PARSE (params,
+ "branch", JSONRPC_MESSAGE_GET_STRING (&branch)
+ );
+
+ if (!r || !(destination = g_file_new_for_uri (dest_uri)))
+ {
+ client_op_bad_params (op);
+ return;
+ }
+
+ op->token = g_strdup (token);
+
+ callbacks = gbp_git_remote_callbacks_new ();
+
+ g_signal_connect_data (callbacks,
+ "progress",
+ G_CALLBACK (handle_clone_url_transfer_cb),
+ client_op_ref (op),
+ (GClosureNotify)client_op_unref,
+ 0);
+
+ g_signal_connect_data (callbacks,
+ "transfer-progress",
+ G_CALLBACK (handle_clone_url_transfer_progress_cb),
+ client_op_ref (op),
+ (GClosureNotify)client_op_unref,
+ 0);
+
+ fetch_options = ggit_fetch_options_new ();
+ ggit_fetch_options_set_remote_callbacks (fetch_options, GGIT_REMOTE_CALLBACKS (callbacks));
+
+ options = ggit_clone_options_new ();
+ ggit_clone_options_set_is_bare (options, FALSE);
+ ggit_clone_options_set_checkout_branch (options, branch ? branch : "master");
+ ggit_clone_options_set_fetch_options (options, fetch_options);
+
+ gbp_git_clone_url_async (git,
+ url,
+ destination,
+ options,
+ op->cancellable,
+ (GAsyncReadyCallback)handle_clone_url_cb,
+ client_op_ref (op));
+
+ g_clear_pointer (&fetch_options, ggit_fetch_options_free);
+}
+
/* Main Loop and Setup {{{1 */
gint
@@ -528,6 +714,7 @@ main (gint argc,
jsonrpc_server_add_handler (server, method, (JsonrpcServerHandler)func, g_object_ref (git), g_object_unref)
ADD_HANDLER ("initialize", handle_initialize);
+ ADD_HANDLER ("git/cloneUrl", handle_clone_url);
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]