[gnome-builder/wip/chergert/git-oop: 6/12] add api to do submodule updates in worker
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/chergert/git-oop: 6/12] add api to do submodule updates in worker
- Date: Thu, 21 Mar 2019 05:13:50 +0000 (UTC)
commit 9a9ce40a1c89b949a40d8bb29fb1c054b492793a
Author: Christian Hergert <chergert redhat com>
Date: Wed Mar 20 14:48:20 2019 -0700
add api to do submodule updates in worker
src/plugins/git/gbp-git-client.c | 75 +++++++++++
src/plugins/git/gbp-git-client.h | 8 ++
src/plugins/git/gbp-git.c | 118 +++++++++++++++++
src/plugins/git/gbp-git.h | 100 ++++++++-------
src/plugins/git/gnome-builder-git.c | 250 ++++++++++++++++++++++--------------
5 files changed, 408 insertions(+), 143 deletions(-)
---
diff --git a/src/plugins/git/gbp-git-client.c b/src/plugins/git/gbp-git-client.c
index 7a15c0b88..91bba30a2 100644
--- a/src/plugins/git/gbp-git-client.c
+++ b/src/plugins/git/gbp-git-client.c
@@ -742,3 +742,78 @@ gbp_git_client_clone_url_finish (GbpGitClient *self,
return ide_task_propagate_boolean (IDE_TASK (result), error);
}
+
+static void
+gbp_git_client_update_submodules_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GbpGitClient *self = (GbpGitClient *)object;
+ g_autoptr(IdeTask) task = user_data;
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GError) error = NULL;
+ const gchar *token = NULL;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (GBP_IS_GIT_CLIENT (self));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (IDE_IS_TASK (task));
+
+ if (!gbp_git_client_call_finish (self, result, &reply, &error))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_task_return_boolean (task, TRUE);
+
+ if ((token = ide_task_get_task_data (task)) && self->notif_by_token)
+ g_hash_table_remove (self->notif_by_token, token);
+}
+
+void
+gbp_git_client_update_submodules_async (GbpGitClient *self,
+ IdeNotification *notif,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(IdeTask) task = NULL;
+ g_autoptr(GVariant) command = NULL;
+ g_autofree gchar *token = NULL;
+
+ g_return_if_fail (GBP_IS_GIT_CLIENT (self));
+ g_return_if_fail (!notif || IDE_IS_NOTIFICATION (notif));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = ide_task_new (self, cancellable, callback, user_data);
+ ide_task_set_source_tag (task, gbp_git_client_update_submodules_async);
+
+ if (notif != NULL)
+ {
+ token = gbp_git_client_track_progress (self, notif);
+ ide_notification_set_title (notif, _("Updating Git Submodules"));
+ ide_notification_set_icon_name (notif, "builder-vcs-git-symbolic");
+ ide_notification_set_progress (notif, 0.0);
+ ide_task_set_task_data (task, g_strdup (token), g_free);
+ }
+
+ command = JSONRPC_MESSAGE_NEW (
+ "token", JSONRPC_MESSAGE_PUT_STRING (token)
+ );
+
+ gbp_git_client_call_async (self,
+ "git/updateSubmodules",
+ command,
+ cancellable,
+ gbp_git_client_update_submodules_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+gbp_git_client_update_submodules_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (GBP_IS_GIT_CLIENT (self), FALSE);
+ g_return_val_if_fail (IDE_IS_TASK (result), FALSE);
+
+ return ide_task_propagate_boolean (IDE_TASK (result), error);
+}
diff --git a/src/plugins/git/gbp-git-client.h b/src/plugins/git/gbp-git-client.h
index 299a2be64..a28792867 100644
--- a/src/plugins/git/gbp-git-client.h
+++ b/src/plugins/git/gbp-git-client.h
@@ -91,5 +91,13 @@ void gbp_git_client_clone_url_async (GbpGitClient *s
gboolean gbp_git_client_clone_url_finish (GbpGitClient *self,
GAsyncResult *result,
GError **error);
+void gbp_git_client_update_submodules_async (GbpGitClient *self,
+ IdeNotification *notif,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_client_update_submodules_finish (GbpGitClient *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/plugins/git/gbp-git.c b/src/plugins/git/gbp-git.c
index ae460c739..ef01c87f3 100644
--- a/src/plugins/git/gbp-git.c
+++ b/src/plugins/git/gbp-git.c
@@ -342,3 +342,121 @@ gbp_git_clone_url_finish (GbpGit *self,
return g_task_propagate_boolean (G_TASK (result), error);
}
+
+typedef struct
+{
+ GFile *workdir;
+ GgitSubmoduleUpdateOptions *options;
+ GError *error;
+} UpdateSubmodules;
+
+static void
+update_submodules_free (UpdateSubmodules *state)
+{
+ g_clear_object (&state->workdir);
+ g_clear_object (&state->options);
+ g_clear_error (&state->error);
+ g_slice_free (UpdateSubmodules, state);
+}
+
+static gint
+gbp_git_update_submodules_foreach_submodule_cb (GgitSubmodule *submodule,
+ const gchar *name,
+ gpointer user_data)
+{
+ UpdateSubmodules *state = user_data;
+
+ g_assert (submodule != NULL);
+ g_assert (name != NULL);
+ g_assert (state != NULL);
+
+ if (state->error != NULL)
+ ggit_submodule_update (submodule,
+ FALSE,
+ state->options,
+ &state->error);
+
+ return GIT_OK;
+}
+
+static void
+gbp_git_update_submodules_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ UpdateSubmodules *state = task_data;
+ g_autoptr(GgitRepository) repository = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (GBP_IS_GIT (source_object));
+ g_assert (state != NULL);
+ g_assert (G_IS_FILE (state->workdir));
+ g_assert (GGIT_IS_SUBMODULE_UPDATE_OPTIONS (state->options));
+
+ if (!(repository = ggit_repository_open (state->workdir, &error)))
+ goto handle_error;
+
+ if (!ggit_repository_submodule_foreach (repository,
+ gbp_git_update_submodules_foreach_submodule_cb,
+ state,
+ &error))
+ goto handle_error;
+
+ error = g_steal_pointer (&state->error);
+
+handle_error:
+
+ if (error != NULL)
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+void
+gbp_git_update_submodules_async (GbpGit *self,
+ GgitSubmoduleUpdateOptions *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ UpdateSubmodules *state;
+
+ g_assert (GBP_IS_GIT (self));
+ g_assert (GGIT_IS_SUBMODULE_UPDATE_OPTIONS (options));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, gbp_git_clone_url_async);
+
+ if (self->workdir == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_INITIALIZED,
+ "No workdir has been set for the project");
+ return;
+ }
+
+ state = g_slice_new0 (UpdateSubmodules);
+ state->options = g_object_ref (options);
+ state->workdir = g_object_ref (self->workdir);
+
+ g_task_set_priority (task, G_PRIORITY_LOW);
+ g_task_set_task_data (task, state, (GDestroyNotify)update_submodules_free);
+ g_task_set_return_on_cancel (task, TRUE);
+ g_task_run_in_thread (task, gbp_git_update_submodules_worker);
+}
+
+gboolean
+gbp_git_update_submodules_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 63133b51e..b117e1780 100644
--- a/src/plugins/git/gbp-git.h
+++ b/src/plugins/git/gbp-git.h
@@ -53,51 +53,59 @@ typedef void (*GbpGitProgress) (const gchar *message,
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_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);
+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);
+void gbp_git_update_submodules_async (GbpGit *self,
+ GgitSubmoduleUpdateOptions *options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gbp_git_update_submodules_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 76686d426..560e15d0f 100644
--- a/src/plugins/git/gnome-builder-git.c
+++ b/src/plugins/git/gnome-builder-git.c
@@ -134,26 +134,6 @@ client_op_new (JsonrpcClient *client,
return op;
}
-static void
-handle_reply_cb (JsonrpcClient *client,
- GAsyncResult *result,
- gpointer user_data)
-{
- g_autoptr(GError) error = NULL;
- g_autoptr(ClientOp) op = user_data;
-
- g_assert (JSONRPC_IS_CLIENT (client));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (op != NULL);
- g_assert (op->client == client);
-
- if (!jsonrpc_client_reply_finish (client, result, &error))
- {
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning ("Reply failed: %s", error->message);
- }
-}
-
static void
client_op_notify (ClientOp *op,
const gchar *method,
@@ -169,35 +149,43 @@ client_op_notify (ClientOp *op,
NULL);
}
+
static void
-client_op_reply (ClientOp *op,
- GVariant *reply)
+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);
- g_assert (op->client != NULL);
- jsonrpc_client_reply_async (op->client,
- op->id,
- reply,
- op->cancellable,
- (GAsyncReadyCallback)handle_reply_cb,
- client_op_ref (op));
+ 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
-progress_cb (goffset current_num_bytes,
- goffset total_num_bytes,
- gpointer user_data)
+transfer_progress_cb (GbpGitRemoteCallbacks *callbacks,
+ GgitTransferProgress *stats,
+ ClientOp *op)
{
- ClientOp *op = user_data;
g_autoptr(GVariant) reply = NULL;
+ gdouble total;
+ gdouble received;
gdouble progress = 0.0;
+ g_assert (GBP_GIT_REMOTE_CALLBACKS (callbacks));
g_assert (op != NULL);
- g_assert (op->client != NULL);
- if (total_num_bytes > 0)
- progress = (gdouble)current_num_bytes / (gdouble)total_num_bytes;
+ 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),
@@ -207,6 +195,70 @@ progress_cb (goffset current_num_bytes,
client_op_notify (op, "$/progress", reply);
}
+static GgitRemoteCallbacks *
+create_callbacks_for_op (ClientOp *op)
+{
+ GgitRemoteCallbacks *ret;
+
+ g_assert (op != NULL);
+
+ ret = gbp_git_remote_callbacks_new ();
+
+ if (op->token != NULL)
+ {
+ g_signal_connect_data (ret,
+ "progress",
+ G_CALLBACK (transfer_cb),
+ client_op_ref (op),
+ (GClosureNotify)client_op_unref,
+ 0);
+
+ g_signal_connect_data (ret,
+ "transfer-progress",
+ G_CALLBACK (transfer_progress_cb),
+ client_op_ref (op),
+ (GClosureNotify)client_op_unref,
+ 0);
+ }
+
+ return g_steal_pointer (&ret);
+}
+
+static void
+handle_reply_cb (JsonrpcClient *client,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ g_autoptr(ClientOp) op = user_data;
+
+ g_assert (JSONRPC_IS_CLIENT (client));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (op != NULL);
+ g_assert (op->client == client);
+
+ if (!jsonrpc_client_reply_finish (client, result, &error))
+ {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Reply failed: %s", error->message);
+ }
+}
+
+static void
+client_op_reply (ClientOp *op,
+ GVariant *reply)
+{
+ g_assert (op != NULL);
+ g_assert (op->client != NULL);
+
+ jsonrpc_client_reply_async (op->client,
+ op->id,
+ reply,
+ op->cancellable,
+ (GAsyncReadyCallback)handle_reply_cb,
+ client_op_ref (op));
+}
+
/* Initialize {{{1 */
static void
@@ -548,51 +600,6 @@ handle_clone_url_cb (GbpGit *git,
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,
@@ -637,24 +644,10 @@ handle_clone_url (JsonrpcServer *server,
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);
+ callbacks = create_callbacks_for_op (op);
fetch_options = ggit_fetch_options_new ();
- ggit_fetch_options_set_remote_callbacks (fetch_options, GGIT_REMOTE_CALLBACKS (callbacks));
+ ggit_fetch_options_set_remote_callbacks (fetch_options, callbacks);
options = ggit_clone_options_new ();
ggit_clone_options_set_is_bare (options, FALSE);
@@ -672,6 +665,68 @@ handle_clone_url (JsonrpcServer *server,
g_clear_pointer (&fetch_options, ggit_fetch_options_free);
}
+/* Handle Submodule Updating {{{1 */
+
+static void
+handle_update_submodules_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_update_submodules_finish (git, result, &error))
+ client_op_error (op, error);
+ else
+ client_op_reply (op, g_variant_new_boolean (TRUE));
+}
+
+static void
+handle_update_submodules (JsonrpcServer *server,
+ JsonrpcClient *client,
+ const gchar *method,
+ GVariant *id,
+ GVariant *params,
+ GbpGit *git)
+{
+ g_autoptr(ClientOp) op = NULL;
+ g_autoptr(GgitRemoteCallbacks) callbacks = NULL;
+ g_autoptr(GgitSubmoduleUpdateOptions) update_options = NULL;
+ GgitFetchOptions *fetch_options = NULL;
+ const gchar *token = NULL;
+
+ g_assert (JSONRPC_IS_SERVER (server));
+ g_assert (JSONRPC_IS_CLIENT (client));
+ g_assert (g_str_equal (method, "git/updateSubmodules"));
+ g_assert (id != NULL);
+ g_assert (GBP_IS_GIT (git));
+
+ op = client_op_new (client, id);
+
+ if (!JSONRPC_MESSAGE_PARSE (params, "token", JSONRPC_MESSAGE_GET_STRING (&token)))
+ token = NULL;
+
+ callbacks = create_callbacks_for_op (op);
+
+ fetch_options = ggit_fetch_options_new ();
+ ggit_fetch_options_set_remote_callbacks (fetch_options, callbacks);
+
+ update_options = ggit_submodule_update_options_new ();
+ ggit_submodule_update_options_set_fetch_options (update_options, fetch_options);
+
+ gbp_git_update_submodules_async (git,
+ update_options,
+ op->cancellable,
+ (GAsyncReadyCallback)handle_update_submodules_cb,
+ client_op_ref (op));
+
+ g_clear_pointer (&fetch_options, ggit_fetch_options_free);
+}
+
/* Main Loop and Setup {{{1 */
gint
@@ -717,6 +772,7 @@ main (gint argc,
ADD_HANDLER ("git/isIgnored", handle_is_ignored);
ADD_HANDLER ("git/listRefsByKind", handle_list_refs_by_kind);
ADD_HANDLER ("git/switchBranch", handle_switch_branch);
+ ADD_HANDLER ("git/updateSubmodules", handle_update_submodules);
ADD_HANDLER ("$/cancelRequest", handle_cancel_request);
#undef ADD_HANDLER
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]