1 /*
2 * ggit-remote-callbacks.c
3 * This file is part of libgit2-glib
4 *
5 * Copyright (C) 2013 - Ignacio Casal Quinteiro
6 *
7 * libgit2-glib is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * libgit2-glib is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with libgit2-glib. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "ggit-remote-callbacks.h"
22 #include "ggit-cred.h"
23 #include "ggit-transfer-progress.h"
24 #include "ggit-oid.h"
25 #include "ggit-enum-types.h"
26
27 /**
28 * GgitRemoteCallbacks:
29 *
30 * Represents a git remote callbacks.
31 */
32
33 typedef struct _GgitRemoteCallbacksPrivate
34 {
35 git_remote_callbacks native;
36 } GgitRemoteCallbacksPrivate;
37
38 enum
39 {
40 PROGRESS,
41 TRANSFER_PROGRESS,
42 UPDATE_TIPS,
43 COMPLETION,
44 NUM_SIGNALS
45 };
46
47 static guint signals[NUM_SIGNALS] = {0,};
48
49 /**
50 * GgitRemoteCallbacksClass::credentials:
51 * @callbacks: a #GgitRemoteCallbacks.
52 * @url: the url.
53 * @username_from_url: (allow-none): the username extracted from the url.
54 * @allowed_types: the allowed credential types.
55 * @error: a #GError for error reporting.
56 *
57 * Returns: (transfer full) (nullable): a #GgitCred or %NULL in case of an error.
58 */
59
G_DEFINE_TYPE_WITH_PRIVATE(GgitRemoteCallbacks,ggit_remote_callbacks,G_TYPE_OBJECT)60 G_DEFINE_TYPE_WITH_PRIVATE (GgitRemoteCallbacks, ggit_remote_callbacks, G_TYPE_OBJECT)
61
62 static void
63 ggit_remote_callbacks_finalize (GObject *object)
64 {
65 GgitRemoteCallbacks *callbacks = GGIT_REMOTE_CALLBACKS (object);
66 GgitRemoteCallbacksPrivate *priv;
67
68 priv = ggit_remote_callbacks_get_instance_private (callbacks);
69
70 priv->native.payload = NULL;
71
72 G_OBJECT_CLASS (ggit_remote_callbacks_parent_class)->finalize (object);
73 }
74
75 static void
ggit_remote_callbacks_class_init(GgitRemoteCallbacksClass * klass)76 ggit_remote_callbacks_class_init (GgitRemoteCallbacksClass *klass)
77 {
78 GObjectClass *object_class = G_OBJECT_CLASS (klass);
79
80 object_class->finalize = ggit_remote_callbacks_finalize;
81
82 signals[UPDATE_TIPS] =
83 g_signal_new ("update-tips",
84 G_TYPE_FROM_CLASS (object_class),
85 G_SIGNAL_RUN_LAST,
86 G_STRUCT_OFFSET (GgitRemoteCallbacksClass, update_tips),
87 NULL, NULL,
88 NULL,
89 G_TYPE_NONE,
90 3,
91 G_TYPE_STRING,
92 GGIT_TYPE_OID,
93 GGIT_TYPE_OID);
94
95 signals[PROGRESS] =
96 g_signal_new ("progress",
97 G_TYPE_FROM_CLASS (object_class),
98 G_SIGNAL_RUN_LAST,
99 G_STRUCT_OFFSET (GgitRemoteCallbacksClass, progress),
100 NULL, NULL,
101 NULL,
102 G_TYPE_NONE,
103 1,
104 G_TYPE_STRING);
105
106 signals[TRANSFER_PROGRESS] =
107 g_signal_new ("transfer-progress",
108 G_TYPE_FROM_CLASS (object_class),
109 G_SIGNAL_RUN_LAST,
110 G_STRUCT_OFFSET (GgitRemoteCallbacksClass, transfer_progress),
111 NULL, NULL,
112 NULL,
113 G_TYPE_NONE,
114 1,
115 GGIT_TYPE_TRANSFER_PROGRESS);
116
117 signals[COMPLETION] =
118 g_signal_new ("completion",
119 G_TYPE_FROM_CLASS (object_class),
120 G_SIGNAL_RUN_LAST,
121 G_STRUCT_OFFSET (GgitRemoteCallbacksClass, completion),
122 NULL, NULL,
123 NULL,
124 G_TYPE_NONE,
125 1,
126 GGIT_TYPE_REMOTE_COMPLETION_TYPE);
127 }
128
129 static int
credentials_wrap(git_cred ** cred,const char * url,const char * username_from_url,unsigned int allowed_types,void * data)130 credentials_wrap (git_cred **cred,
131 const char *url,
132 const char *username_from_url,
133 unsigned int allowed_types,
134 void *data)
135 {
136 GgitRemoteCallbacks *callbacks = GGIT_REMOTE_CALLBACKS (data);
137 GgitRemoteCallbacksClass *cls = GGIT_REMOTE_CALLBACKS_GET_CLASS (callbacks);
138
139 *cred = NULL;
140
141 if (cls->credentials != NULL)
142 {
143 GgitCred *mcred = NULL;
144 GError *error = NULL;
145
146 mcred = cls->credentials (callbacks,
147 url,
148 username_from_url,
149 allowed_types,
150 &error);
151
152 if (mcred != NULL)
153 {
154 *cred = _ggit_native_release (mcred);
155 g_object_unref (mcred);
156
157 return GIT_OK;
158 }
159 else
160 {
161 if (error)
162 {
163 #if LIBGIT2_VER_MAJOR > 0 || (LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR >= 28)
164 git_error_set_str (GIT_ERROR, error->message);
165 #else
166 giterr_set_str (GIT_ERROR, error->message);
167 #endif
168 g_error_free (error);
169
170 return GIT_ERROR;
171 }
172 else
173 {
174 return GIT_PASSTHROUGH;
175 }
176 }
177 }
178 else
179 {
180 return GIT_OK;
181 }
182 }
183
184
185 static int
progress_wrap(const char * str,int len,void * data)186 progress_wrap (const char *str,
187 int len,
188 void *data)
189 {
190 GgitRemoteCallbacks *callbacks = GGIT_REMOTE_CALLBACKS (data);
191 gchar *message;
192
193 message = g_strndup (str, len);
194
195 g_signal_emit (callbacks, signals[PROGRESS], 0, message);
196
197 g_free (message);
198 return GIT_OK;
199 }
200
201 static int
transfer_progress_wrap(const git_transfer_progress * stats,void * data)202 transfer_progress_wrap (const git_transfer_progress *stats,
203 void *data)
204 {
205 GgitRemoteCallbacks *callbacks = GGIT_REMOTE_CALLBACKS (data);
206 GgitTransferProgress *p;
207
208 p = _ggit_transfer_progress_wrap (stats);
209
210 g_signal_emit (callbacks, signals[TRANSFER_PROGRESS], 0, p);
211 ggit_transfer_progress_free (p);
212
213 return GIT_OK;
214 }
215
216 static int
update_tips_wrap(const char * refname,const git_oid * a,const git_oid * b,void * data)217 update_tips_wrap (const char *refname,
218 const git_oid *a,
219 const git_oid *b,
220 void *data)
221 {
222 GgitRemoteCallbacks *callbacks = GGIT_REMOTE_CALLBACKS (data);
223 GgitOId *na;
224 GgitOId *nb;
225
226 na = _ggit_oid_wrap (a);
227 nb = _ggit_oid_wrap (b);
228
229 g_signal_emit (callbacks, signals[UPDATE_TIPS], 0, refname, na, nb);
230
231 ggit_oid_free (na);
232 ggit_oid_free (nb);
233
234 return GIT_OK;
235 }
236
237 static int
completion_wrap(git_remote_completion_type type,void * data)238 completion_wrap (git_remote_completion_type type,
239 void *data)
240 {
241 GgitRemoteCallbacks *callbacks = GGIT_REMOTE_CALLBACKS (data);
242 GgitRemoteCompletionType rt = (GgitRemoteCompletionType)type;
243
244 g_signal_emit (callbacks, signals[COMPLETION], 0, rt);
245
246 return GIT_OK;
247 }
248
249 static void
ggit_remote_callbacks_init(GgitRemoteCallbacks * callbacks)250 ggit_remote_callbacks_init (GgitRemoteCallbacks *callbacks)
251 {
252 GgitRemoteCallbacksPrivate *priv;
253
254 git_remote_callbacks gcallbacks = GIT_REMOTE_CALLBACKS_INIT;
255
256 priv = ggit_remote_callbacks_get_instance_private (callbacks);
257
258 priv->native = gcallbacks;
259
260 priv->native.sideband_progress = progress_wrap;
261 priv->native.transfer_progress = transfer_progress_wrap;
262 priv->native.update_tips = update_tips_wrap;
263 priv->native.completion = completion_wrap;
264
265 priv->native.credentials = credentials_wrap;
266
267 priv->native.payload = callbacks;
268 }
269
270 git_remote_callbacks *
_ggit_remote_callbacks_get_native(GgitRemoteCallbacks * callbacks)271 _ggit_remote_callbacks_get_native (GgitRemoteCallbacks *callbacks)
272 {
273 GgitRemoteCallbacksPrivate *priv;
274
275 priv = ggit_remote_callbacks_get_instance_private (callbacks);
276
277 return &priv->native;
278 }
279
280 /* ex:set ts=8 noet: */
281