1 /* gbp-git-workbench-addin.c
2  *
3  * Copyright 2019 Christian Hergert <chergert@redhat.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * SPDX-License-Identifier: GPL-3.0-or-later
19  */
20 
21 #define G_LOG_DOMAIN "gbp-git-workbench-addin"
22 
23 #include "config.h"
24 
25 #include <libide-vcs.h>
26 
27 #include "daemon/ipc-git-service.h"
28 
29 #include "gbp-git-client.h"
30 #include "gbp-git-workbench-addin.h"
31 #include "gbp-git-vcs.h"
32 
33 struct _GbpGitWorkbenchAddin
34 {
35   GObject       parent_instance;
36   IdeWorkbench *workbench;
37 };
38 
39 static void
gbp_git_workbench_addin_load_project_new_cb(GObject * object,GAsyncResult * result,gpointer user_data)40 gbp_git_workbench_addin_load_project_new_cb (GObject      *object,
41                                              GAsyncResult *result,
42                                              gpointer      user_data)
43 {
44   GbpGitWorkbenchAddin *self;
45   g_autoptr(IpcGitRepository) repository = NULL;
46   g_autoptr(IdeTask) task = user_data;
47   g_autoptr(GError) error = NULL;
48 
49   g_assert (G_IS_ASYNC_RESULT (result));
50   g_assert (IDE_IS_TASK (task));
51 
52   if (!(repository = ipc_git_repository_proxy_new_finish (result, &error)))
53     {
54       ide_task_return_error (task, g_steal_pointer (&error));
55       return;
56     }
57 
58   self = ide_task_get_source_object (task);
59 
60   if (self->workbench != NULL)
61     {
62       g_autoptr(GbpGitVcs) vcs = gbp_git_vcs_new (repository);
63 
64       ide_workbench_set_vcs (self->workbench, IDE_VCS (vcs));
65     }
66 
67   ide_task_return_boolean (task, TRUE);
68 }
69 
70 static void
gbp_git_workbench_addin_load_project_open_cb(GObject * object,GAsyncResult * result,gpointer user_data)71 gbp_git_workbench_addin_load_project_open_cb (GObject      *object,
72                                               GAsyncResult *result,
73                                               gpointer      user_data)
74 {
75   IpcGitService *service = (IpcGitService *)object;
76   g_autofree gchar *obj_path = NULL;
77   g_autoptr(IdeTask) task = user_data;
78   g_autoptr(GError) error = NULL;
79   GDBusConnection *connection;
80 
81   g_assert (IPC_IS_GIT_SERVICE (service));
82   g_assert (G_IS_ASYNC_RESULT (result));
83   g_assert (IDE_IS_TASK (task));
84 
85   connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (service));
86 
87   if (!ipc_git_service_call_open_finish (service, &obj_path, result, &error))
88     ide_task_return_error (task, g_steal_pointer (&error));
89   else
90     ipc_git_repository_proxy_new (connection,
91                                   G_DBUS_PROXY_FLAGS_NONE,
92                                   NULL,
93                                   obj_path,
94                                   ide_task_get_cancellable (task),
95                                   gbp_git_workbench_addin_load_project_new_cb,
96                                   g_object_ref (task));
97 }
98 
99 static void
gbp_git_workbench_addin_load_project_discover_cb(GObject * object,GAsyncResult * result,gpointer user_data)100 gbp_git_workbench_addin_load_project_discover_cb (GObject      *object,
101                                                   GAsyncResult *result,
102                                                   gpointer      user_data)
103 {
104   IpcGitService *service = (IpcGitService *)object;
105   g_autofree gchar *git_location = NULL;
106   g_autoptr(IdeTask) task = user_data;
107   g_autoptr(GError) error = NULL;
108 
109   g_assert (IPC_IS_GIT_SERVICE (service));
110   g_assert (G_IS_ASYNC_RESULT (result));
111   g_assert (IDE_IS_TASK (task));
112 
113   if (!ipc_git_service_call_discover_finish (service, &git_location, result, &error))
114     {
115       g_dbus_error_strip_remote_error (error);
116       ide_task_return_error (task, g_steal_pointer (&error));
117       return;
118     }
119 
120   ipc_git_service_call_open (service,
121                              git_location,
122                              ide_task_get_cancellable (task),
123                              gbp_git_workbench_addin_load_project_open_cb,
124                              g_object_ref (task));
125 }
126 
127 static void
gbp_git_workbench_addin_load_project_service_cb(GObject * object,GAsyncResult * result,gpointer user_data)128 gbp_git_workbench_addin_load_project_service_cb (GObject      *object,
129                                                  GAsyncResult *result,
130                                                  gpointer      user_data)
131 {
132   GbpGitClient *client = (GbpGitClient *)object;
133   g_autoptr(IpcGitService) service = NULL;
134   g_autoptr(IdeTask) task = user_data;
135   g_autoptr(GError) error = NULL;
136   IdeProjectInfo *project_info;
137   GFile *directory;
138 
139   g_assert (GBP_IS_GIT_CLIENT (client));
140   g_assert (G_IS_ASYNC_RESULT (result));
141   g_assert (IDE_IS_TASK (task));
142 
143   if (!(service = gbp_git_client_get_service_finish (client, result, &error)))
144     {
145       ide_task_return_error (task, g_steal_pointer (&error));
146       return;
147     }
148 
149   project_info = ide_task_get_task_data (task);
150   directory = ide_project_info_get_directory (project_info);
151 
152   if (!g_file_is_native (directory))
153     {
154       ide_task_return_new_error (task,
155                                  G_IO_ERROR,
156                                  G_IO_ERROR_NOT_SUPPORTED,
157                                  "Cannot initialize git, not a local file-system");
158       return;
159     }
160 
161   ipc_git_service_call_discover (service,
162                                  g_file_peek_path (directory),
163                                  ide_task_get_cancellable (task),
164                                  gbp_git_workbench_addin_load_project_discover_cb,
165                                  g_object_ref (task));
166 }
167 
168 static void
gbp_git_workbench_addin_load_project_async(IdeWorkbenchAddin * addin,IdeProjectInfo * project_info,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)169 gbp_git_workbench_addin_load_project_async (IdeWorkbenchAddin   *addin,
170                                             IdeProjectInfo      *project_info,
171                                             GCancellable        *cancellable,
172                                             GAsyncReadyCallback  callback,
173                                             gpointer             user_data)
174 {
175   GbpGitWorkbenchAddin *self = (GbpGitWorkbenchAddin *)addin;
176   g_autoptr(IdeTask) task = NULL;
177   GbpGitClient *client;
178   IdeContext *context;
179 
180   g_assert (GBP_IS_GIT_WORKBENCH_ADDIN (self));
181   g_assert (IDE_IS_PROJECT_INFO (project_info));
182   g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
183 
184   task = ide_task_new (self, cancellable, callback, user_data);
185   ide_task_set_source_tag (task, gbp_git_workbench_addin_load_project_async);
186   ide_task_set_task_data (task, g_object_ref (project_info), g_object_unref);
187 
188   context = ide_workbench_get_context (self->workbench);
189   client = gbp_git_client_from_context (context);
190 
191   gbp_git_client_get_service_async (client,
192                                     cancellable,
193                                     gbp_git_workbench_addin_load_project_service_cb,
194                                     g_steal_pointer (&task));
195 }
196 
197 static gboolean
gbp_git_workbench_addin_load_project_finish(IdeWorkbenchAddin * addin,GAsyncResult * result,GError ** error)198 gbp_git_workbench_addin_load_project_finish (IdeWorkbenchAddin  *addin,
199                                              GAsyncResult       *result,
200                                              GError            **error)
201 {
202   g_assert (GBP_IS_GIT_WORKBENCH_ADDIN (addin));
203   g_assert (IDE_IS_TASK (result));
204 
205   return ide_task_propagate_boolean (IDE_TASK (result), error);
206 }
207 
208 static void
gbp_git_workbench_addin_load(IdeWorkbenchAddin * addin,IdeWorkbench * workbench)209 gbp_git_workbench_addin_load (IdeWorkbenchAddin *addin,
210                               IdeWorkbench      *workbench)
211 {
212   GbpGitWorkbenchAddin *self = (GbpGitWorkbenchAddin *)addin;
213 
214   g_assert (GBP_IS_GIT_WORKBENCH_ADDIN (self));
215   g_assert (IDE_IS_WORKBENCH (workbench));
216 
217   self->workbench = workbench;
218 }
219 
220 static void
gbp_git_workbench_addin_unload(IdeWorkbenchAddin * addin,IdeWorkbench * workbench)221 gbp_git_workbench_addin_unload (IdeWorkbenchAddin *addin,
222                                 IdeWorkbench      *workbench)
223 {
224   GbpGitWorkbenchAddin *self = (GbpGitWorkbenchAddin *)addin;
225 
226   g_assert (GBP_IS_GIT_WORKBENCH_ADDIN (self));
227   g_assert (IDE_IS_WORKBENCH (workbench));
228 
229   self->workbench = NULL;
230 }
231 
232 static void
workbench_addin_iface_init(IdeWorkbenchAddinInterface * iface)233 workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
234 {
235   iface->load = gbp_git_workbench_addin_load;
236   iface->unload = gbp_git_workbench_addin_unload;
237   iface->load_project_async = gbp_git_workbench_addin_load_project_async;
238   iface->load_project_finish = gbp_git_workbench_addin_load_project_finish;
239 }
240 
G_DEFINE_FINAL_TYPE_WITH_CODE(GbpGitWorkbenchAddin,gbp_git_workbench_addin,G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN,workbench_addin_iface_init))241 G_DEFINE_FINAL_TYPE_WITH_CODE (GbpGitWorkbenchAddin, gbp_git_workbench_addin, G_TYPE_OBJECT,
242                          G_IMPLEMENT_INTERFACE (IDE_TYPE_WORKBENCH_ADDIN, workbench_addin_iface_init))
243 
244 static void
245 gbp_git_workbench_addin_class_init (GbpGitWorkbenchAddinClass *klass)
246 {
247 }
248 
249 static void
gbp_git_workbench_addin_init(GbpGitWorkbenchAddin * self)250 gbp_git_workbench_addin_init (GbpGitWorkbenchAddin *self)
251 {
252 }
253