[libgit2-glib] Bind blame file
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgit2-glib] Bind blame file
- Date: Mon, 25 Nov 2013 11:51:46 +0000 (UTC)
commit 0e83587ead6e51b9c625de7e103761c1f74856f7
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Mon Nov 25 12:51:14 2013 +0100
Bind blame file
libgit2-glib/Makefile.am | 2 +
libgit2-glib/ggit-blame.c | 341 ++++++++++++++++++++++++++++++++++++++++
libgit2-glib/ggit-blame.h | 87 ++++++++++
libgit2-glib/ggit-repository.c | 46 ++++++
libgit2-glib/ggit-repository.h | 5 +
libgit2-glib/ggit-types.h | 14 ++
6 files changed, 495 insertions(+), 0 deletions(-)
---
diff --git a/libgit2-glib/Makefile.am b/libgit2-glib/Makefile.am
index 4173b1a..b85d497 100644
--- a/libgit2-glib/Makefile.am
+++ b/libgit2-glib/Makefile.am
@@ -18,6 +18,7 @@ libgit2_glib_1_0_la_LDFLAGS = \
libgit2_glib_1_0_la_LIBADD = $(LIBGIT2_GLIB_LIBS)
INST_H_FILES = \
+ ggit-blame.h \
ggit-blame-options.h \
ggit-blob.h \
ggit-blob-output-stream.h \
@@ -74,6 +75,7 @@ NOINST_H_FILES = \
ggit-utils.h
C_FILES = \
+ ggit-blame.c \
ggit-blame-options.c \
ggit-blob.c \
ggit-blob-output-stream.c \
diff --git a/libgit2-glib/ggit-blame.c b/libgit2-glib/ggit-blame.c
new file mode 100644
index 0000000..ae8e240
--- /dev/null
+++ b/libgit2-glib/ggit-blame.c
@@ -0,0 +1,341 @@
+/*
+ * ggit-blame.h
+ * This file is part of libgit2-glib
+ *
+ * Copyright (C) 2013 - Jesse van den Kieboom
+ *
+ * libgit2-glib is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libgit2-glib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libgit2-glib. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ggit-blame.h"
+#include "ggit-oid.h"
+#include "ggit-signature.h"
+
+struct _GgitBlameHunk
+{
+ guint16 lines_in_hunk;
+
+ GgitOId *final_commit_id;
+ guint16 final_start_line_number;
+ GgitSignature *final_signature;
+
+ GgitOId *orig_commit_id;
+ gchar *orig_path;
+ guint16 orig_start_line_number;
+ GgitSignature *orig_signature;
+
+ gboolean boundary;
+
+ gint ref_count;
+};
+
+G_DEFINE_TYPE (GgitBlame, ggit_blame, GGIT_TYPE_NATIVE)
+
+G_DEFINE_BOXED_TYPE (GgitBlameHunk, ggit_blame_hunk,
+ ggit_blame_hunk_ref, ggit_blame_hunk_unref);
+
+/**
+ * ggit_blame_hunk_ref:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Atomically increments the reference count of @blame_hunk by one.
+ * This function is MT-safe and may be called from any thread.
+ *
+ * Returns: (transfer none): a #GgitBlameHunk.
+ */
+GgitBlameHunk *
+ggit_blame_hunk_ref (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, NULL);
+
+ g_atomic_int_inc (&blame_hunk->ref_count);
+
+ return blame_hunk;
+}
+
+/**
+ * ggit_blame_hunk_unref:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Atomically decrements the reference count of @blame_hunk by one.
+ * If the reference count drops to 0, @blame_hunk is freed.
+ */
+void
+ggit_blame_hunk_unref (GgitBlameHunk *blame_hunk)
+{
+ g_return_if_fail (blame_hunk != NULL);
+
+ if (g_atomic_int_dec_and_test (&blame_hunk->ref_count))
+ {
+ if (blame_hunk->final_commit_id != NULL)
+ {
+ ggit_oid_free (blame_hunk->final_commit_id);
+ }
+
+ g_clear_object (&blame_hunk->final_signature);
+
+ if (blame_hunk->orig_commit_id != NULL)
+ {
+ ggit_oid_free (blame_hunk->orig_commit_id);
+ }
+
+ g_clear_object (&blame_hunk->orig_signature);
+
+ g_free (blame_hunk->orig_path);
+
+ g_slice_free (GgitBlameHunk, blame_hunk);
+ }
+}
+
+static GgitBlameHunk *
+ggit_blame_hunk_wrap (const git_blame_hunk *gblame_hunk)
+{
+ GgitBlameHunk *blame_hunk;
+
+ blame_hunk = g_slice_new0 (GgitBlameHunk);
+ blame_hunk->ref_count = 1;
+
+ blame_hunk->lines_in_hunk = gblame_hunk->lines_in_hunk;
+
+ blame_hunk->final_commit_id = _ggit_oid_wrap (&gblame_hunk->final_commit_id);
+ blame_hunk->final_start_line_number = gblame_hunk->final_start_line_number;
+
+ if (gblame_hunk->final_signature)
+ {
+ blame_hunk->final_signature =
+ _ggit_signature_wrap (gblame_hunk->final_signature,
+ NULL,
+ FALSE);
+ }
+
+ blame_hunk->orig_commit_id = _ggit_oid_wrap (&gblame_hunk->orig_commit_id);
+ blame_hunk->orig_start_line_number = gblame_hunk->orig_start_line_number;
+
+ if (gblame_hunk->orig_signature)
+ {
+ blame_hunk->orig_signature =
+ _ggit_signature_wrap (gblame_hunk->orig_signature,
+ NULL,
+ FALSE);
+ }
+
+ blame_hunk->orig_path = g_strdup (gblame_hunk->orig_path);
+ return blame_hunk;
+}
+
+/**
+ * ggit_blame_hunk_get_lines_in_hunk:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the number of lines in the hunk.
+ *
+ * Returns: the number of lines in the hunk.
+ *
+ **/
+guint16
+ggit_blame_hunk_get_lines_in_hunk (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, 0);
+
+ return blame_hunk->lines_in_hunk;
+}
+
+/**
+ * ggit_blame_hunk_get_final_commit_id:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the id of the commit where this hunk was last changed.
+ *
+ * Returns: (transfer none): a #GgitOId.
+ *
+ **/
+GgitOId *
+ggit_blame_hunk_get_final_commit_id (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, NULL);
+
+ return blame_hunk->final_commit_id;
+}
+
+/**
+ * ggit_blame_hunk_get_final_start_line_number:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the line number where the hunk begins in the final version of the file.
+ * Line numbers start at 1.
+ *
+ * Returns: the final hunk line number.
+ *
+ **/
+guint16
+ggit_blame_hunk_get_final_start_line_number (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, 0);
+
+ return blame_hunk->final_start_line_number;
+}
+
+/**
+ * ggit_blame_hunk_get_final_signature:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the signature of the final version of the hunk.
+ *
+ * Returns: (transfer none): a #GgitSignature.
+ *
+ **/
+GgitSignature *
+ggit_blame_hunk_get_final_signature (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, NULL);
+
+ return blame_hunk->final_signature;
+}
+
+/**
+ * ggit_blame_hunk_get_orig_commit_id:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the id of the commit where the hunk was found. This is usually the same
+ * the final commit id, except when #GGIT_BLAME_TRACK_COPIES_ANY_COMMIT was used.
+ *
+ * Returns: (transfer none): a #GgitOId.
+ *
+ **/
+GgitOId *
+ggit_blame_hunk_get_orig_commit_id (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, NULL);
+
+ return blame_hunk->orig_commit_id;
+}
+
+/**
+ * ggit_blame_hunk_get_orig_start_line_number:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the line number where the hunk begins in the file specified by
+ * #ggit_blame_hunk_get_orig_path at the commit specified by
+ * #ggit_blame_hunk_get_orig_commit_id. Line numbers start at 1.
+ *
+ * Returns: the orig hunk line number.
+ *
+ **/
+guint16
+ggit_blame_hunk_get_orig_start_line_number (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, 0);
+
+ return blame_hunk->orig_start_line_number;
+}
+
+/**
+ * ggit_blame_hunk_get_orig_signature:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the signature of the commit specified by #ggit_blame_hunk_get_orig_commit_id.
+ *
+ * Returns: (transfer none): a #GgitSignature.
+ *
+ **/
+GgitSignature *
+ggit_blame_hunk_get_orig_signature (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, NULL);
+
+ return blame_hunk->orig_signature;
+}
+
+/**
+ * ggit_blame_hunk_get_orig_path:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get the path of the file where this hunk originated, as of the commit
+ * specified by #ggit_blame_hunk_get_orig_commit_id.
+ *
+ * Returns: the path.
+ */
+const gchar *
+ggit_blame_hunk_get_orig_path (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, NULL);
+
+ return blame_hunk->orig_path;
+}
+
+/**
+ * ggit_blame_hunk_is_boundary:
+ * @blame_hunk: a #GgitBlameHunk.
+ *
+ * Get whether the hunk has been tracked to a boundary commit (the root,
+ * or the commit specified in #ggit_blame_options_set_oldest_commit).
+ *
+ * Returns: whether the hunk is at a boundary commit.
+ *
+ **/
+gboolean
+ggit_blame_hunk_is_boundary (GgitBlameHunk *blame_hunk)
+{
+ g_return_val_if_fail (blame_hunk != NULL, FALSE);
+
+ return blame_hunk->boundary;
+}
+
+static void
+ggit_blame_class_init (GgitBlameClass *klass)
+{
+}
+
+static void
+ggit_blame_init (GgitBlame *self)
+{
+}
+
+GgitBlame *
+_ggit_blame_wrap (git_blame *blame)
+{
+ GgitBlame *ret;
+
+ ret = g_object_new (GGIT_TYPE_BLAME, NULL);
+ _ggit_native_set (ret, blame, (GDestroyNotify)git_blame_free);
+
+ return ret;
+}
+
+guint32
+ggit_blame_get_hunk_count (GgitBlame *blame)
+{
+ g_return_val_if_fail (GGIT_IS_BLAME (blame), 0);
+ return git_blame_get_hunk_count (_ggit_native_get (blame));
+}
+
+GgitBlameHunk *
+ggit_blame_get_hunk_by_line (GgitBlame *blame,
+ guint32 line)
+{
+ g_return_val_if_fail (GGIT_IS_BLAME (blame), NULL);
+
+ return ggit_blame_hunk_wrap (git_blame_get_hunk_byline (_ggit_native_get (blame),
+ line));
+}
+
+GgitBlameHunk *
+ggit_blame_get_hunk_by_index (GgitBlame *blame,
+ guint32 idx)
+{
+ g_return_val_if_fail (GGIT_IS_BLAME (blame), NULL);
+
+ return ggit_blame_hunk_wrap (git_blame_get_hunk_byindex (_ggit_native_get (blame),
+ idx));
+}
diff --git a/libgit2-glib/ggit-blame.h b/libgit2-glib/ggit-blame.h
new file mode 100644
index 0000000..cc562b2
--- /dev/null
+++ b/libgit2-glib/ggit-blame.h
@@ -0,0 +1,87 @@
+/*
+ * ggit-blame.h
+ * This file is part of libgit2-glib
+ *
+ * Copyright (C) 2013 - Jesse van den Kieboom
+ *
+ * libgit2-glib is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * libgit2-glib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with libgit2-glib. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GGIT_BLAME_H__
+#define __GGIT_BLAME_H__
+
+#include <glib-object.h>
+#include <libgit2-glib/ggit-native.h>
+#include <libgit2-glib/ggit-types.h>
+#include <git2.h>
+
+G_BEGIN_DECLS
+
+#define GGIT_TYPE_BLAME (ggit_blame_get_type ())
+#define GGIT_BLAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GGIT_TYPE_BLAME,
GgitBlame))
+#define GGIT_BLAME_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GGIT_TYPE_BLAME, GgitBlame const))
+#define GGIT_BLAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GGIT_TYPE_BLAME,
GgitBlameClass))
+#define GGIT_IS_BLAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GGIT_TYPE_BLAME))
+#define GGIT_IS_BLAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GGIT_TYPE_BLAME))
+#define GGIT_BLAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GGIT_TYPE_BLAME, GgitBlameClass))
+
+typedef struct _GgitBlameClass GgitBlameClass;
+
+struct _GgitBlame
+{
+ /*< private >*/
+ GgitNative parent;
+
+ /* priv padding */
+ gpointer priv;
+};
+
+struct _GgitBlameClass
+{
+ /*< private >*/
+ GgitNativeClass parent_class;
+};
+
+GType ggit_blame_hunk_get_type (void) G_GNUC_CONST;
+GgitBlameHunk *ggit_blame_hunk_ref (GgitBlameHunk *blame_hunk);
+void ggit_blame_hunk_unref (GgitBlameHunk *blame_hunk);
+
+guint16 ggit_blame_hunk_get_lines_in_hunk (GgitBlameHunk *blame_hunk);
+
+GgitOId *ggit_blame_hunk_get_final_commit_id (GgitBlameHunk *blame_hunk);
+guint16 ggit_blame_hunk_get_final_start_line_number (GgitBlameHunk *blame_hunk);
+GgitSignature *ggit_blame_hunk_get_final_signature (GgitBlameHunk *blame_hunk);
+
+GgitOId *ggit_blame_hunk_get_orig_commit_id (GgitBlameHunk *blame_hunk);
+guint16 ggit_blame_hunk_get_orig_start_line_number (GgitBlameHunk *blame_hunk);
+GgitSignature *ggit_blame_hunk_get_orig_signature (GgitBlameHunk *blame_hunk);
+const gchar *ggit_blame_hunk_get_orig_path (GgitBlameHunk *blame_hunk);
+
+gboolean ggit_blame_hunk_is_boundary (GgitBlameHunk *blame_hunk);
+
+GType ggit_blame_get_type (void) G_GNUC_CONST;
+
+GgitBlame *_ggit_blame_wrap (git_blame *blame);
+
+guint32 ggit_blame_get_hunk_count (GgitBlame *blame);
+
+GgitBlameHunk *ggit_blame_get_hunk_by_line (GgitBlame *blame,
+ guint32 line);
+
+GgitBlameHunk *ggit_blame_get_hunk_by_index (GgitBlame *blame,
+ guint32 idx);
+
+G_END_DECLS
+
+#endif /* __GGIT_BLAME_H__ */
diff --git a/libgit2-glib/ggit-repository.c b/libgit2-glib/ggit-repository.c
index d1fab4b..9e1d058 100644
--- a/libgit2-glib/ggit-repository.c
+++ b/libgit2-glib/ggit-repository.c
@@ -34,6 +34,8 @@
#include "ggit-status-options.h"
#include "ggit-tree-builder.h"
#include "ggit-branch-enumerator.h"
+#include "ggit-blame.h"
+#include "ggit-blame-options.h"
#define GGIT_REPOSITORY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), GGIT_TYPE_REPOSITORY,
GgitRepositoryPrivate))
@@ -2348,4 +2350,48 @@ ggit_repository_create_index_entry_for_path (GgitRepository *repository,
return ret;
}
+/**
+ * ggit_repository_blame_file:
+ * @repository: a #GgitRepository.
+ * @file: the file to blame.
+ * @blame_options: (allow-none): blame options.
+ * @error: a #GError.
+ *
+ * Get a blame for a single file.
+ *
+ * Returns: (transfer full): a #GgitBlame.
+ *
+ **/
+GgitBlame *
+ggit_repository_blame_file (GgitRepository *repository,
+ GFile *file,
+ GgitBlameOptions *blame_options,
+ GError **error)
+{
+ git_blame *blame;
+ gchar *path;
+ int ret;
+
+ g_return_val_if_fail (GGIT_IS_REPOSITORY (repository), NULL);
+ g_return_val_if_fail (G_IS_FILE (file), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ path = g_file_get_relative_path (repository->priv->workdir, file);
+
+ ret = git_blame_file (&blame,
+ _ggit_native_get (repository),
+ path,
+ _ggit_blame_options_get_blame_options (blame_options));
+
+ g_free (path);
+
+ if (ret != GIT_OK)
+ {
+ _ggit_error_set (error, ret);
+ return NULL;
+ }
+
+ return _ggit_blame_wrap (blame);
+}
+
/* ex:set ts=8 noet: */
diff --git a/libgit2-glib/ggit-repository.h b/libgit2-glib/ggit-repository.h
index 94eac5e..8f2a348 100644
--- a/libgit2-glib/ggit-repository.h
+++ b/libgit2-glib/ggit-repository.h
@@ -305,6 +305,11 @@ void ggit_repository_get_ahead_behind (GgitRepository *re
gsize *behind,
GError **error);
+GgitBlame *ggit_repository_blame_file (GgitRepository *repository,
+ GFile *file,
+ GgitBlameOptions *blame_options,
+ GError **error);
+
G_END_DECLS
#endif /* __GGIT_REPOSITORY_H__ */
diff --git a/libgit2-glib/ggit-types.h b/libgit2-glib/ggit-types.h
index 7072206..97a9ae5 100644
--- a/libgit2-glib/ggit-types.h
+++ b/libgit2-glib/ggit-types.h
@@ -152,6 +152,20 @@ typedef struct _GgitDiffOptions GgitDiffOptions;
typedef struct _GgitDiffSimilarityMetric GgitDiffSimilarityMetric;
/**
+ * GgitBlame:
+ *
+ * Represents a blame.
+ */
+typedef struct _GgitBlame GgitBlame;
+
+/**
+ * GgitBlameHunk:
+ *
+ * Represents a blame hunk.
+ */
+typedef struct _GgitBlameHunk GgitBlameHunk;
+
+/**
* GgitIndex:
*
* Represents an index object.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]