[libgit2-glib] Implement ggit_diff_line_get_text
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgit2-glib] Implement ggit_diff_line_get_text
- Date: Fri, 27 Dec 2013 15:22:39 +0000 (UTC)
commit d40bb525c9307af6ccfe9c3cc1fee6a2f16b52b3
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Fri Dec 27 16:20:10 2013 +0100
Implement ggit_diff_line_get_text
Retrieve the encoding of a file from either the gui.encoding config
value, or (with higher priority) the encoding file attribute. If set,
ggit_diff_line_get_text will convert from that encoding to utf-8 and
ensures a utf-8 encoded string is returned. Characters that cannot be
decoded will contain the fallback ? character.
libgit2-glib/ggit-diff-line.c | 34 +++++++-
libgit2-glib/ggit-diff-line.h | 5 +-
libgit2-glib/ggit-diff.c | 187 +++++++++++++++++++++++++++++++++++++----
libgit2-glib/ggit-diff.h | 7 +-
4 files changed, 210 insertions(+), 23 deletions(-)
---
diff --git a/libgit2-glib/ggit-diff-line.c b/libgit2-glib/ggit-diff-line.c
index f135856..6c78b0d 100644
--- a/libgit2-glib/ggit-diff-line.c
+++ b/libgit2-glib/ggit-diff-line.c
@@ -22,6 +22,7 @@
#include <git2.h>
#include "ggit-diff-line.h"
+#include "ggit-convert.h"
struct _GgitDiffLine {
gint ref_count;
@@ -33,6 +34,9 @@ struct _GgitDiffLine {
gsize content_len;
gint64 content_offset;
const gchar *content;
+
+ gchar *text;
+ const gchar *encoding;
};
G_DEFINE_BOXED_TYPE (GgitDiffLine, ggit_diff_line,
@@ -40,7 +44,8 @@ G_DEFINE_BOXED_TYPE (GgitDiffLine, ggit_diff_line,
GgitDiffLine *
-_ggit_diff_line_wrap (const git_diff_line *line)
+_ggit_diff_line_wrap (const git_diff_line *line,
+ const gchar *encoding)
{
GgitDiffLine *gline;
@@ -54,6 +59,8 @@ _ggit_diff_line_wrap (const git_diff_line *line)
gline->content_len = line->content_len;
gline->content_offset = line->content_offset;
gline->content = line->content;
+ gline->encoding = encoding;
+ gline->text = NULL;
return gline;
}
@@ -91,6 +98,7 @@ ggit_diff_line_unref (GgitDiffLine *line)
if (g_atomic_int_dec_and_test (&line->ref_count))
{
+ g_free (line->text);
g_slice_free (GgitDiffLine, line);
}
}
@@ -182,4 +190,28 @@ ggit_diff_line_get_content (GgitDiffLine *line,
return (const guint8 *)line->content;
}
+/**
+ * ggit_diff_line_get_text:
+ * @line: a #GgitDiffLine.
+ *
+ * Get the content of the diff line as UTF-8 encoded text.
+ *
+ * Returns: the content in utf-8 encoding.
+ *
+ **/
+const gchar *
+ggit_diff_line_get_text (GgitDiffLine *line)
+{
+ g_return_val_if_fail (line != NULL, NULL);
+
+ if (line->text == NULL)
+ {
+ line->text = ggit_convert_utf8 (line->content,
+ line->content_len,
+ line->encoding);
+ }
+
+ return line->text;
+}
+
/* ex:set ts=8 noet: */
diff --git a/libgit2-glib/ggit-diff-line.h b/libgit2-glib/ggit-diff-line.h
index f055187..2181937 100644
--- a/libgit2-glib/ggit-diff-line.h
+++ b/libgit2-glib/ggit-diff-line.h
@@ -30,7 +30,8 @@ G_BEGIN_DECLS
GType ggit_diff_line_get_type (void) G_GNUC_CONST;
-GgitDiffLine *_ggit_diff_line_wrap (const git_diff_line *line);
+GgitDiffLine *_ggit_diff_line_wrap (const git_diff_line *line,
+ const gchar *encoding);
GgitDiffLine *ggit_diff_line_ref (GgitDiffLine *line);
void ggit_diff_line_unref (GgitDiffLine *line);
@@ -43,6 +44,8 @@ gint64 ggit_diff_line_get_content_offset (GgitDiffLine *line);
const guint8 *ggit_diff_line_get_content (GgitDiffLine *line,
gsize *length);
+const gchar *ggit_diff_line_get_text (GgitDiffLine *line);
+
G_END_DECLS
#endif /* __GGIT_DIFF_LINE_H__ */
diff --git a/libgit2-glib/ggit-diff.c b/libgit2-glib/ggit-diff.c
index 7580d8b..143068c 100644
--- a/libgit2-glib/ggit-diff.c
+++ b/libgit2-glib/ggit-diff.c
@@ -28,8 +28,20 @@
#include "ggit-patch.h"
#include "ggit-error.h"
#include "ggit-repository.h"
+#include "ggit-diff-file.h"
+
+#define GGIT_DIFF_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GGIT_TYPE_DIFF, GgitDiffPrivate))
+
+struct _GgitDiffPrivate
+{
+ GgitRepository *repository;
+ gchar *encoding;
+};
typedef struct {
+ GgitDiff *diff;
+ const gchar *encoding;
+
gpointer user_data;
GgitDiffFileCallback file_cb;
@@ -39,6 +51,12 @@ typedef struct {
G_DEFINE_TYPE (GgitDiff, ggit_diff, GGIT_TYPE_NATIVE)
+enum
+{
+ PROP_0,
+ PROP_REPOSITORY
+};
+
static gint
ggit_diff_file_callback_wrapper (const git_diff_delta *delta,
gfloat progress,
@@ -50,6 +68,36 @@ ggit_diff_file_callback_wrapper (const git_diff_delta *delta,
gdelta = _ggit_diff_delta_wrap (delta);
+ data->encoding = NULL;
+
+ if (data->diff != NULL)
+ {
+ GgitDiffFile *file;
+
+ if (ggit_diff_delta_get_status (gdelta) == GGIT_DELTA_DELETED)
+ {
+ file = ggit_diff_delta_get_old_file (gdelta);
+ }
+ else
+ {
+ file = ggit_diff_delta_get_new_file (gdelta);
+ }
+
+ if (file != NULL)
+ {
+ const gchar *path;
+
+ path = ggit_diff_file_get_path (file);
+
+ data->encoding =
+ ggit_repository_get_attribute (data->diff->priv->repository,
+ path,
+ "encoding",
+ GGIT_ATTRIBUTE_CHECK_FILE_THEN_INDEX,
+ NULL);
+ }
+ }
+
ret = data->file_cb (gdelta, progress, data->user_data);
ggit_diff_delta_unref (gdelta);
@@ -89,10 +137,20 @@ ggit_diff_line_callback_wrapper (const git_diff_delta *delta,
GgitDiffHunk *ghunk;
GgitDiffLine *gline;
gint ret;
+ const gchar *encoding = NULL;
+
+ if (data->encoding != NULL)
+ {
+ encoding = data->encoding;
+ }
+ else if (data->diff != NULL)
+ {
+ encoding = data->diff->priv->encoding;
+ }
gdelta = _ggit_diff_delta_wrap (delta);
ghunk = hunk == NULL ? NULL : _ggit_diff_hunk_wrap (hunk);
- gline = line == NULL ? NULL : _ggit_diff_line_wrap (line);
+ gline = line == NULL ? NULL : _ggit_diff_line_wrap (line, encoding);
ret = data->line_cb (gdelta, ghunk, gline, data->user_data);
@@ -112,29 +170,117 @@ ggit_diff_line_callback_wrapper (const git_diff_delta *delta,
}
static void
-ggit_diff_class_init (GgitDiffClass *klass)
+ggit_diff_finalize (GObject *object)
{
+ GgitDiffPrivate *priv = GGIT_DIFF (object)->priv;
+
+ g_free (priv->encoding);
+
+ G_OBJECT_CLASS (ggit_diff_parent_class)->finalize (object);
}
static void
-ggit_diff_init (GgitDiff *self)
+ggit_diff_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
+ GgitDiff *self = GGIT_DIFF (object);
+
+ switch (prop_id)
+ {
+ case PROP_REPOSITORY:
+ self->priv->repository = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
}
-GgitDiff *
-_ggit_diff_wrap (git_diff *diff,
- gboolean owned)
+static void
+ggit_diff_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
{
- GgitDiff *gdiff;
+ GgitDiff *self = GGIT_DIFF (object);
- gdiff = g_object_new (GGIT_TYPE_DIFF, NULL);
- _ggit_native_set (gdiff, diff, NULL);
+ switch (prop_id)
+ {
+ case PROP_REPOSITORY:
+ g_value_set_object (value, self->priv->repository);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
- if (owned)
+static void
+ggit_diff_constructed (GObject *object)
+{
+ GgitDiffPrivate *priv = GGIT_DIFF (object)->priv;
+ GgitConfig *config = NULL;
+
+ if (priv->repository != NULL)
{
- _ggit_native_set_destroy_func (gdiff,
- (GDestroyNotify)git_diff_free);
+ config = ggit_repository_get_config (priv->repository, NULL);
+ }
+
+ if (config != NULL)
+ {
+ const gchar *enc;
+
+ enc = ggit_config_get_string (config, "gui.encoding", NULL);
+
+ if (enc != NULL)
+ {
+ priv->encoding = g_strdup (enc);
+ }
+
+ g_object_unref (config);
}
+}
+
+static void
+ggit_diff_class_init (GgitDiffClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ggit_diff_finalize;
+ object_class->constructed = ggit_diff_constructed;
+
+ object_class->get_property = ggit_diff_get_property;
+ object_class->set_property = ggit_diff_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_REPOSITORY,
+ g_param_spec_object ("repository",
+ "Repository",
+ "Repository",
+ GGIT_TYPE_REPOSITORY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (object_class, sizeof (GgitDiffPrivate));
+}
+
+static void
+ggit_diff_init (GgitDiff *self)
+{
+ self->priv = GGIT_DIFF_GET_PRIVATE (self);
+}
+
+static GgitDiff *
+_ggit_diff_wrap (GgitRepository *repository,
+ git_diff *diff)
+{
+ GgitDiff *gdiff;
+
+ gdiff = g_object_new (GGIT_TYPE_DIFF, "repository", repository, NULL);
+ _ggit_native_set (gdiff, diff, (GDestroyNotify)git_diff_free);
return gdiff;
}
@@ -182,7 +328,7 @@ ggit_diff_new_tree_to_tree (GgitRepository *repository,
return NULL;
}
- return _ggit_diff_wrap (diff, TRUE);
+ return _ggit_diff_wrap (repository, diff);
}
/**
@@ -228,7 +374,7 @@ ggit_diff_new_tree_to_index (GgitRepository *repository,
return NULL;
}
- return _ggit_diff_wrap (diff, TRUE);
+ return _ggit_diff_wrap (repository, diff);
}
/**
@@ -270,7 +416,7 @@ ggit_diff_new_index_to_workdir (GgitRepository *repository,
return NULL;
}
- return _ggit_diff_wrap (diff, TRUE);
+ return _ggit_diff_wrap (repository, diff);
}
/**
@@ -311,7 +457,7 @@ ggit_diff_new_tree_to_workdir (GgitRepository *repository,
return NULL;
}
- return _ggit_diff_wrap (diff, TRUE);
+ return _ggit_diff_wrap (repository, diff);
}
/**
@@ -375,6 +521,8 @@ ggit_diff_foreach (GgitDiff *diff,
g_return_if_fail (error == NULL || *error == NULL);
wrapper_data.user_data = user_data;
+ wrapper_data.diff = diff;
+ wrapper_data.encoding = NULL;
if (file_cb != NULL)
{
@@ -429,6 +577,9 @@ ggit_diff_print (GgitDiff *diff,
g_return_if_fail (error == NULL || *error == NULL);
wrapper_data.user_data = user_data;
+ wrapper_data.diff = diff;
+ wrapper_data.encoding = NULL;
+
wrapper_data.line_cb = print_cb;
ret = git_diff_print (_ggit_native_get (diff), (git_diff_format_t)type,
@@ -506,6 +657,8 @@ ggit_diff_blobs (GgitBlob *old_blob,
gdiff_options = _ggit_diff_options_get_diff_options (diff_options);
wrapper_data.user_data = user_data;
+ wrapper_data.diff = NULL;
+ wrapper_data.encoding = NULL;
if (file_cb != NULL)
{
@@ -583,6 +736,8 @@ ggit_diff_blob_to_buffer (GgitBlob *old_blob,
gdiff_options = _ggit_diff_options_get_diff_options (diff_options);
wrapper_data.user_data = user_data;
+ wrapper_data.diff = NULL;
+ wrapper_data.encoding = NULL;
if (file_cb != NULL)
{
diff --git a/libgit2-glib/ggit-diff.h b/libgit2-glib/ggit-diff.h
index 169a494..1c39bcb 100644
--- a/libgit2-glib/ggit-diff.h
+++ b/libgit2-glib/ggit-diff.h
@@ -35,14 +35,14 @@ G_BEGIN_DECLS
#define GGIT_DIFF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GGIT_TYPE_DIFF, GgitDiffClass))
typedef struct _GgitDiffClass GgitDiffClass;
+typedef struct _GgitDiffPrivate GgitDiffPrivate;
struct _GgitDiff
{
/*< private >*/
GgitNative parent;
- /* priv padding */
- gpointer priv;
+ GgitDiffPrivate *priv;
};
/**
@@ -59,9 +59,6 @@ struct _GgitDiffClass
GType ggit_diff_get_type (void) G_GNUC_CONST;
-GgitDiff *_ggit_diff_wrap (git_diff *diff,
- gboolean owned);
-
GgitDiff *ggit_diff_new_tree_to_tree (GgitRepository *repository,
GgitTree *old_tree,
GgitTree *new_tree,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]