[libgit2-glib: 1/3] diff: Cache object by content, not location
- From: Alberto Fanjul <albfan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgit2-glib: 1/3] diff: Cache object by content, not location
- Date: Thu, 1 Nov 2018 09:31:38 +0000 (UTC)
commit 8433c18e4284890bf34f4c4829df3fd7f9bfe530
Author: Martin Blanchard <tchaik gmx com>
Date: Mon Jan 22 15:57:53 2018 +0100
diff: Cache object by content, not location
Diff objects (deltas and hunks) from libgit2 are cached in a hash
table, using object's memory locations as keys. In some cases,
libgit2 does not generate new delta and hunk objects but simply
modify its first allocated struct in place. git_diff_blob_to_buffer()
function does so for hunks, for example, thus breaking the memory
location based index logic of libgit2-glib.
This patch makes the index logic rely on actual object's content
instead of memory location. Index for deltas are generated from
'old_file' git oid. Index for hunks are generated from a combination
of its belonging delta's 'old_file' git oid and its own header.
https://bugzilla.gnome.org/show_bug.cgi?id=792733
https://gitlab.gnome.org/GNOME/gitg/issues/109
libgit2-glib/ggit-diff.c | 57 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 48 insertions(+), 9 deletions(-)
---
diff --git a/libgit2-glib/ggit-diff.c b/libgit2-glib/ggit-diff.c
index 640d946..83e1303 100644
--- a/libgit2-glib/ggit-diff.c
+++ b/libgit2-glib/ggit-diff.c
@@ -76,18 +76,36 @@ wrap_diff_delta_cached (CallbackWrapperData *data,
const git_diff_delta *delta)
{
GgitDiffDelta *gdelta;
+ gchar *key;
if (!delta)
{
return NULL;
}
- gdelta = g_hash_table_lookup (data->cached_deltas, delta);
+ if (delta->old_file.path != NULL)
+ {
+ key = g_strdup_printf ("%s%s",
+ delta->old_file.path,
+ git_oid_tostr_s (&delta->old_file.id));
+ }
+ else
+ {
+ key = g_strdup_printf ("%s%s",
+ delta->new_file.path,
+ git_oid_tostr_s (&delta->new_file.id));
+ }
+
+ gdelta = g_hash_table_lookup (data->cached_deltas, key);
if (!gdelta)
{
gdelta = _ggit_diff_delta_wrap (delta);
- g_hash_table_insert (data->cached_deltas, (gpointer) delta, gdelta);
+ g_hash_table_insert (data->cached_deltas, key, gdelta);
+ }
+ else
+ {
+ g_free (key);
}
return gdelta;
@@ -95,21 +113,42 @@ wrap_diff_delta_cached (CallbackWrapperData *data,
static GgitDiffHunk *
wrap_diff_hunk_cached (CallbackWrapperData *data,
+ const git_diff_delta *delta,
const git_diff_hunk *hunk)
{
GgitDiffHunk *ghunk;
+ gchar *key;
- if (!hunk)
+ if (!delta || !hunk)
{
return NULL;
}
- ghunk = g_hash_table_lookup (data->cached_hunks, hunk);
+ if (delta->old_file.path != NULL)
+ {
+ key = g_strdup_printf ("%s%s%s",
+ delta->old_file.path,
+ git_oid_tostr_s (&delta->old_file.id),
+ hunk->header);
+ }
+ else
+ {
+ key = g_strdup_printf ("%s%s%s",
+ delta->new_file.path,
+ git_oid_tostr_s (&delta->new_file.id),
+ hunk->header);
+ }
+
+ ghunk = g_hash_table_lookup (data->cached_hunks, key);
if (!ghunk)
{
ghunk = _ggit_diff_hunk_wrap (hunk);
- g_hash_table_insert (data->cached_hunks, (gpointer) hunk, ghunk);
+ g_hash_table_insert (data->cached_hunks, g_strdup (key), ghunk);
+ }
+ else
+ {
+ g_free (key);
}
return ghunk;
@@ -195,7 +234,7 @@ ggit_diff_hunk_callback_wrapper (const git_diff_delta *delta,
gint ret;
gdelta = wrap_diff_delta_cached (data, delta);
- ghunk = wrap_diff_hunk_cached (data, hunk);
+ ghunk = wrap_diff_hunk_cached (data, delta, hunk);
ret = data->hunk_cb (gdelta, ghunk, data->user_data);
@@ -228,7 +267,7 @@ ggit_diff_line_callback_wrapper (const git_diff_delta *delta,
}
gdelta = wrap_diff_delta_cached (data, delta);
- ghunk = wrap_diff_hunk_cached (data, hunk);
+ ghunk = wrap_diff_hunk_cached (data, delta, hunk);
gline = line == NULL ? NULL : _ggit_diff_line_wrap (line, encoding);
@@ -613,8 +652,8 @@ ggit_diff_foreach (GgitDiff *diff,
wrapper_data.user_data = user_data;
wrapper_data.diff = diff;
- wrapper_data.cached_deltas = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) ggit_diff_delta_unref);
- wrapper_data.cached_hunks = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) ggit_diff_hunk_unref);
+ wrapper_data.cached_deltas = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)
ggit_diff_delta_unref);
+ wrapper_data.cached_hunks = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)
ggit_diff_hunk_unref);
if (file_cb != NULL)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]