[libgit2-glib] Implement GgitRemoteCallbacks as a class



commit 503408416b51bf47e478de04e01714f1ea6083d7
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Sat Nov 23 01:16:34 2013 +0100

    Implement GgitRemoteCallbacks as a class

 libgit2-glib/ggit-remote-callbacks.c |  188 ++++++++++++++++++++++++----------
 libgit2-glib/ggit-remote-callbacks.h |   59 +++++++++--
 libgit2-glib/ggit-types.c            |    4 +
 libgit2-glib/ggit-types.h            |   15 +++
 4 files changed, 202 insertions(+), 64 deletions(-)
---
diff --git a/libgit2-glib/ggit-remote-callbacks.c b/libgit2-glib/ggit-remote-callbacks.c
index d518d9d..4928d26 100644
--- a/libgit2-glib/ggit-remote-callbacks.c
+++ b/libgit2-glib/ggit-remote-callbacks.c
@@ -18,85 +18,167 @@
  * along with libgit2-glib. If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <git2.h>
-
 #include "ggit-remote-callbacks.h"
+#include "ggit-cred.h"
+#include "ggit-transfer-progress.h"
+#include "ggit-oid.h"
+
+#define GGIT_REMOTE_CALLBACKS_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), 
GGIT_TYPE_REMOTE_CALLBACKS, GgitRemoteCallbacksPrivate))
 
-struct _GgitRemoteCbs
+struct _GgitRemoteCallbacksPrivate
 {
-       git_remote_callbacks remote_cbs;
-       gint ref_count;
+       git_remote_callbacks native;
 };
 
-G_DEFINE_BOXED_TYPE (GgitRemoteCbs, ggit_remote_cbs,
-                     ggit_remote_cbs_ref, ggit_remote_cbs_unref)
+G_DEFINE_TYPE (GgitRemoteCallbacks, ggit_remote_callbacks, G_TYPE_OBJECT)
 
-const git_remote_callbacks *
-_ggit_remote_cbs_get_remote_callbacks (GgitRemoteCbs *remote_cbs)
+static void
+ggit_remote_callbacks_finalize (GObject *object)
+{
+       GgitRemoteCallbacks *self = GGIT_REMOTE_CALLBACKS (object);
+
+       self->priv->native.payload = NULL;
+
+       G_OBJECT_CLASS (ggit_remote_callbacks_parent_class)->finalize (object);
+}
+
+static void
+ggit_remote_callbacks_class_init (GgitRemoteCallbacksClass *klass)
 {
-       /* NULL is common for remote_cbs as it specifies to use the default
-        * so handle a NULL remote_cbs here instead of in every caller.
-        */
-       if (remote_cbs == NULL)
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = ggit_remote_callbacks_finalize;
+
+       g_type_class_add_private (object_class, sizeof (GgitRemoteCallbacksPrivate));
+}
+
+static int
+progress_wrap (const char *str, int len, void *data)
+{
+       GgitRemoteCallbacks *self = GGIT_REMOTE_CALLBACKS (data);
+
+       if (GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->progress != NULL)
        {
-               return NULL;
+               return GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->progress (self, str, len);
        }
+       else
+       {
+               return GIT_OK;
+       }
+}
+
+static int
+completion_wrap (git_remote_completion_type type, void *data)
+{
+       GgitRemoteCallbacks *self = GGIT_REMOTE_CALLBACKS (data);
 
-       return (const git_remote_callbacks *)&remote_cbs->remote_cbs;
+       if (GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->completion != NULL)
+       {
+               return GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->completion (self, 
(GgitRemoteCompletionType)type);
+       }
+       else
+       {
+               return GIT_OK;
+       }
 }
 
-/**
- * ggit_remote_cbs_ref:
- * @remote_cbs: a #GgitRemoteCbs.
- *
- * Copies @remote_cbs into a newly allocated #GgitRemoteCbs.
- *
- * Returns: (transfer full): a newly allocated #GgitRemoteCbs.
- */
-GgitRemoteCbs *
-ggit_remote_cbs_ref (GgitRemoteCbs *remote_cbs)
+static int
+credentials_wrap (git_cred **cred, const char *url, const char *username_from_url, unsigned int 
allowed_types, void *data)
+{
+       GgitRemoteCallbacks *self = GGIT_REMOTE_CALLBACKS (data);
+
+       if (GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->credentials != NULL)
+       {
+               GgitCred *mcred = NULL;
+               gint ret;
+
+               ret = GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->credentials (self, &mcred, url, 
username_from_url, allowed_types);
+
+               if (mcred != NULL)
+               {
+                       *cred = _ggit_native_get (mcred);
+               }
+               else
+               {
+                       *cred = NULL;
+               }
+
+               return ret;
+       }
+       else
+       {
+               return GIT_OK;
+       }
+}
+
+static int
+transfer_progress_wrap (const git_transfer_progress *stats, void *data)
 {
-       g_return_val_if_fail (remote_cbs != NULL, NULL);
+       GgitRemoteCallbacks *self = GGIT_REMOTE_CALLBACKS (data);
 
-       g_atomic_int_inc (&remote_cbs->ref_count);
+       if (GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->transfer_progress != NULL)
+       {
+               GgitTransferProgress *p;
+               gint ret;
+
+               p = _ggit_transfer_progress_wrap (stats);
 
-       return remote_cbs;
+               ret = GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->transfer_progress (self, p);
+               ggit_transfer_progress_free (p);
+
+               return ret;
+       }
+       else
+       {
+               return GIT_OK;
+       }
 }
 
-/**
- * ggit_remote_cbs_unref:
- * @remote_cbs: a #GgitRemoteCbs.
- *
- * Frees @remote_cbs.
- */
-void
-ggit_remote_cbs_unref (GgitRemoteCbs *remote_cbs)
+static int
+update_tips_wrap (const char *refname, const git_oid *a, const git_oid *b, void *data)
 {
-       g_return_if_fail (remote_cbs != NULL);
+       GgitRemoteCallbacks *self = GGIT_REMOTE_CALLBACKS (data);
+
+       if (GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->update_tips != NULL)
+       {
+               GgitOId *na;
+               GgitOId *nb;
+               gint ret;
+
+               na = _ggit_oid_wrap (a);
+               nb = _ggit_oid_wrap (b);
 
-       if (g_atomic_int_dec_and_test (&remote_cbs->ref_count))
+               ret = GGIT_REMOTE_CALLBACKS_GET_CLASS (self)->update_tips (self, refname, na, nb);
+
+               ggit_oid_free (na);
+               ggit_oid_free (nb);
+
+               return ret;
+       }
+       else
        {
-               g_slice_free (GgitRemoteCbs, remote_cbs);
+               return GIT_OK;
        }
 }
 
-/**
- * ggit_remote_cbs_new:
- *
- * Creates a new #GgitRemoteCbs.
- *
- * Returns: a newly allocated #GgitRemoteCbs.
- */
-GgitRemoteCbs *
-ggit_remote_cbs_new (void)
+static void
+ggit_remote_callbacks_init (GgitRemoteCallbacks *self)
 {
-       GgitRemoteCbs *remote_cbs;
-       git_remote_callbacks gremote_cbs = GIT_REMOTE_CALLBACKS_INIT;
+       self->priv = GGIT_REMOTE_CALLBACKS_GET_PRIVATE (self);
 
-       remote_cbs = g_slice_new (GgitRemoteCbs);
-       remote_cbs->remote_cbs = gremote_cbs;
+       self->priv->native.progress = progress_wrap;
+       self->priv->native.completion = completion_wrap;
+       self->priv->native.credentials = credentials_wrap;
+       self->priv->native.transfer_progress = transfer_progress_wrap;
+       self->priv->native.update_tips = update_tips_wrap;
 
-       return remote_cbs;
+       self->priv->native.payload = self;
+}
+
+const git_remote_callbacks *
+_ggit_remote_callbacks_get_native (GgitRemoteCallbacks *self)
+{
+       return &self->priv->native;
 }
 
 /* ex:set ts=8 noet: */
diff --git a/libgit2-glib/ggit-remote-callbacks.h b/libgit2-glib/ggit-remote-callbacks.h
index 0daa9df..8d8e1b9 100644
--- a/libgit2-glib/ggit-remote-callbacks.h
+++ b/libgit2-glib/ggit-remote-callbacks.h
@@ -19,27 +19,64 @@
  */
 
 
-#ifndef __GGIT_REMOTE_CBS_H__
-#define __GGIT_REMOTE_CBS_H__
+#ifndef __GGIT_REMOTE_CALLBACKS_H__
+#define __GGIT_REMOTE_CALLBACKS_H__
 
 #include <glib-object.h>
 #include <git2.h>
-
-#include "ggit-types.h"
+#include <libgit2-glib/ggit-types.h>
 
 G_BEGIN_DECLS
 
-#define GGIT_TYPE_REMOTE_CBS       (ggit_remote_cbs_get_type ())
-#define GGIT_REMOTE_CBS(obj)       ((GgitRemoteCbs *)obj)
+#define GGIT_TYPE_REMOTE_CALLBACKS             (ggit_remote_callbacks_get_type ())
+#define GGIT_REMOTE_CALLBACKS(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GGIT_TYPE_REMOTE_CALLBACKS, GgitRemoteCallbacks))
+#define GGIT_REMOTE_CALLBACKS_CONST(obj)       (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
GGIT_TYPE_REMOTE_CALLBACKS, GgitRemoteCallbacks const))
+#define GGIT_REMOTE_CALLBACKS_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
GGIT_TYPE_REMOTE_CALLBACKS, GgitRemoteCallbacksClass))
+#define GGIT_IS_REMOTE_CALLBACKS(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
GGIT_TYPE_REMOTE_CALLBACKS))
+#define GGIT_IS_REMOTE_CALLBACKS_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GGIT_TYPE_REMOTE_CALLBACKS))
+#define GGIT_REMOTE_CALLBACKS_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GGIT_TYPE_REMOTE_CALLBACKS, GgitRemoteCallbacksClass))
+
+typedef struct _GgitRemoteCallbacks            GgitRemoteCallbacks;
+typedef struct _GgitRemoteCallbacksClass       GgitRemoteCallbacksClass;
+typedef struct _GgitRemoteCallbacksPrivate     GgitRemoteCallbacksPrivate;
+
+struct _GgitRemoteCallbacks
+{
+       GObject parent;
+
+       GgitRemoteCallbacksPrivate *priv;
+};
+
+struct _GgitRemoteCallbacksClass
+{
+       GObjectClass parent_class;
+
+       /* virtual methods */
+       gint (*progress)          (GgitRemoteCallbacks        *callbacks,
+                                  const gchar                *str,
+                                  gint                        len);
+
+       gint (*completion)        (GgitRemoteCallbacks        *callbacks,
+                                  GgitRemoteCompletionType    type);
+
+       gint (*credentials)       (GgitRemoteCallbacks        *callbacks,
+                                  GgitCred                  **cred,
+                                  const gchar                *url,
+                                  const gchar                *username_from_url,
+                                  guint                       allowed_types);
 
-GType                      ggit_remote_cbs_get_type            (void) G_GNUC_CONST;
+       gint (*transfer_progress) (GgitRemoteCallbacks        *callbacks,
+                                  GgitTransferProgress       *stats);
 
-const git_remote_callbacks *_ggit_remote_cbs_get_remote_callbacks  (GgitRemoteCbs        *remote_cbs);
+       gint (*update_tips)       (GgitRemoteCallbacks        *callbacks,
+                                  const gchar                *refname,
+                                  const GgitOId              *a,
+                                  const GgitOId              *b);
+};
 
-GgitRemoteCbs             *ggit_remote_cbs_ref                 (GgitRemoteCbs        *remote_cbs);
-void                       ggit_remote_cbs_unref               (GgitRemoteCbs        *remote_cbs);
+GType                      ggit_remote_callbacks_get_type     (void) G_GNUC_CONST;
 
-GgitRemoteCbs             *ggit_remote_cbs_new                 (void);
+const git_remote_callbacks *_ggit_remote_callbacks_get_native (GgitRemoteCallbacks *remote_cbs);
 
 G_END_DECLS
 
diff --git a/libgit2-glib/ggit-types.c b/libgit2-glib/ggit-types.c
index 0b949cd..0788ff7 100644
--- a/libgit2-glib/ggit-types.c
+++ b/libgit2-glib/ggit-types.c
@@ -122,6 +122,10 @@ ASSERT_ENUM (GGIT_REMOTE_DOWNLOAD_TAGS_AUTO,  GIT_REMOTE_DOWNLOAD_TAGS_AUTO);
 ASSERT_ENUM (GGIT_REMOTE_DOWNLOAD_TAGS_NONE,  GIT_REMOTE_DOWNLOAD_TAGS_NONE);
 ASSERT_ENUM (GGIT_REMOTE_DOWNLOAD_TAGS_ALL,   GIT_REMOTE_DOWNLOAD_TAGS_ALL);
 
+ASSERT_ENUM (GGIT_REMOTE_COMPLETION_DOWNLOAD, GIT_REMOTE_COMPLETION_DOWNLOAD);
+ASSERT_ENUM (GGIT_REMOTE_COMPLETION_INDEXING, GIT_REMOTE_COMPLETION_INDEXING);
+ASSERT_ENUM (GGIT_REMOTE_COMPLETION_ERROR,    GIT_REMOTE_COMPLETION_ERROR);
+
 ASSERT_ENUM (GGIT_REF_INVALID,  GIT_REF_INVALID);
 ASSERT_ENUM (GGIT_REF_OID,      GIT_REF_OID);
 ASSERT_ENUM (GGIT_REF_SYMBOLIC, GIT_REF_SYMBOLIC);
diff --git a/libgit2-glib/ggit-types.h b/libgit2-glib/ggit-types.h
index 0cb11d0..bff69c1 100644
--- a/libgit2-glib/ggit-types.h
+++ b/libgit2-glib/ggit-types.h
@@ -632,6 +632,21 @@ typedef enum {
        GGIT_REMOTE_DOWNLOAD_TAGS_ALL  = 2
 } GgitRemoteDownloadTagsType;
 
+/* NOTE: keep in sync with git2/remote.h */
+/**
+ * GgitRemoteCompletionType:
+ * @GGIT_REMOTE_COMPLETION_DOWNLOAD: download.
+ * @GGIT_REMOTE_COMPLETION_INDEXING: indexing.
+ * @GGIT_REMOTE_COMPLETION_ERROR: error.
+ *
+ * Argument to the completion callback which tells it which operation finished.
+ */
+typedef enum {
+       GGIT_REMOTE_COMPLETION_DOWNLOAD = 0,
+       GGIT_REMOTE_COMPLETION_INDEXING = 1,
+       GGIT_REMOTE_COMPLETION_ERROR = 2
+} GgitRemoteCompletionType;
+
 /* NOTE: keep in sync with git2/refs.h */
 /**
  * GgitRefType:


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