<commit_before>/*
 * ggit-diff.c
 * This file is part of libgit2-glib
 *
 * Copyright (C) 2012 - <NAME>
 *
 * 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 <git2/errors.h>

#include "ggit-diff.h"
#include "ggit-diff-delta.h"
#include "ggit-diff-options.h"
#include "ggit-diff-range.h"
#include "ggit-error.h"
#include "ggit-repository.h"

typedef struct {
	gpointer user_data;

	GgitDiffFileCallback file_cb;
	GgitDiffHunkCallback hunk_cb;
	GgitDiffLineCallback line_cb;
} CallbackWrapperData;

G_DEFINE_TYPE (GgitDiff, ggit_diff, GGIT_TYPE_NATIVE)

static gint
ggit_diff_file_callback_wrapper (const git_diff_delta *delta,
                                 gfloat                progress,
                                 gpointer              user_data)
{
	CallbackWrapperData *data = user_data;
	GgitDiffDelta *gdelta;
	gint ret;

	gdelta = _ggit_diff_delta_wrap (delta);

	ret = data->file_cb (gdelta, progress, data->user_data);

	ggit_diff_delta_unref (gdelta);

	return ret;
}

static gint
ggit_diff_hunk_callback_wrapper (const git_diff_delta *delta,
                                 const git_diff_range *range,
                                 const gchar          *header,
                                 gsize                 header_len,
                                 gpointer              user_data)
{
	CallbackWrapperData *data = user_data;
	GgitDiffDelta *gdelta;
	GgitDiffRange *grange;
	gint ret;

	gdelta = _ggit_diff_delta_wrap (delta);
	grange = _ggit_diff_range_wrap (range);

	ret = data->hunk_cb (gdelta, grange, header, header_len,
	                     data->user_data);

	ggit_diff_range_unref (grange);
	ggit_diff_delta_unref (gdelta);

	return ret;
}

static gint
ggit_diff_line_callback_wrapper (const git_diff_delta *delta,
                                 const git_diff_range *range,
                                 gchar                 line_type,
                                 const gchar          *content,
                                 gsize                 content_len,
                                 gpointer              user_data)
{
	CallbackWrapperData *data = user_data;
	GgitDiffDelta *gdelta;
	GgitDiffRange *grange;
	gint ret;

	gdelta = _ggit_diff_delta_wrap (delta);
	grange = range == NULL ? NULL : _ggit_diff_range_wrap (range);

	ret = data->line_cb (gdelta, grange, (GgitDiffLineType) line_type,
	                     content, content_len, data->user_data);

	if (grange != NULL)
	{
		ggit_diff_range_unref (grange);
	}

	ggit_diff_delta_unref (gdelta);

	return ret;
}

static void
ggit_diff_class_init (GgitDiffClass *klass)
{
}

static void
ggit_diff_init (GgitDiff *self)
{
}

GgitDiff *
_ggit_diff_wrap (git_diff_list *diff,
                 gboolean       owned)
{
	GgitDiff *gdiff;

	gdiff = g_object_new (GGIT_TYPE_DIFF, NULL);
	_ggit_native_set (gdiff, diff, NULL);

	if (owned)
	{
		_ggit_native_set_destroy_func (gdiff,
		                               (GDestroyNotify)git_diff_list_free);
	}

	return gdiff;
}

/**
 * ggit_diff_new_tree_to_tree:
 * @repository: a #GgitRepository.
 * @old_tree: (allow-none): a #GgitTree to diff from.
 * @new_tree: (allow-none): a #GgitTree to diff to.
 * @diff_options: (allow-none): a #GgitDiffOptions, or %NULL.
 * @error: a #GError for error reporting, or %NULL.
 *
 * Creates a #GgitDiff which compares @old_tree and @new_tree.
 *
 * If @diff_options is %NULL then the defaults specified in
 * ggit_diff_options_new() are used.
 *
 * Returns: a newly allocated #GgitDiff if there was no error, %NULL otherwise.
 */
GgitDiff *
ggit_diff_new_tree_to_tree (GgitRepository   *repository,
                            GgitTree         *old_tree,
                            GgitTree         *new_tree,
                            GgitDiffOptions  *diff_options,
                            GError          **error)
{
	git_diff_list *diff;
	gint ret;

	g_return_val_if_fail (GGIT_IS_REPOSITORY (repository), NULL);
	g_return_val_if_fail (old_tree == NULL || GGIT_IS_TREE (old_tree), NULL);
	g_return_val_if_fail (new_tree == NULL || GGIT_IS_TREE (new_tree), NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	ret = git_diff_tree_to_tree (&diff,
	                             _ggit_native_get (repository),
	                             old_tree ? _ggit_native_get (old_tree) : NULL,
	                             new_tree ? _ggit_native_get (new_tree) : NULL,
	                             _ggit_diff_options_get_diff_options (diff_options));

	if (ret != GIT_OK)
	{
		_ggit_error_set (error, ret);
		return NULL;
	}

	return _ggit_diff_wrap (diff, TRUE);
}

/**
 * ggit_diff_new_tree_to_index:
 * @repository: a #GgitRepository.
 * @old_tree: (allow-none): a #GgitTree to diff from.
 * @index: (allow-none): a #GgitIndex, or %NULL.<commit_msg>diff: it is an error to pass NULL for both the `old_tree` and `new_tree`.<commit_after>/*
 * ggit-diff.c
 * This file is part of libgit2-glib
 *
 * Copyright (C) 2012 - <NAME>
 *
 * 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 <git2/errors.h>

#include "ggit-diff.h"
#include "ggit-diff-delta.h"
#include "ggit-diff-options.h"
#include "ggit-diff-range.h"
#include "ggit-error.h"
#include "ggit-repository.h"

typedef struct {
	gpointer user_data;

	GgitDiffFileCallback file_cb;
	GgitDiffHunkCallback hunk_cb;
	GgitDiffLineCallback line_cb;
} CallbackWrapperData;

G_DEFINE_TYPE (GgitDiff, ggit_diff, GGIT_TYPE_NATIVE)

static gint
ggit_diff_file_callback_wrapper (const git_diff_delta *delta,
                                 gfloat                progress,
                                 gpointer              user_data)
{
	CallbackWrapperData *data = user_data;
	GgitDiffDelta *gdelta;
	gint ret;

	gdelta = _ggit_diff_delta_wrap (delta);

	ret = data->file_cb (gdelta, progress, data->user_data);

	ggit_diff_delta_unref (gdelta);

	return ret;
}

static gint
ggit_diff_hunk_callback_wrapper (const git_diff_delta *delta,
                                 const git_diff_range *range,
                                 const gchar          *header,
                                 gsize                 header_len,
                                 gpointer              user_data)
{
	CallbackWrapperData *data = user_data;
	GgitDiffDelta *gdelta;
	GgitDiffRange *grange;
	gint ret;

	gdelta = _ggit_diff_delta_wrap (delta);
	grange = _ggit_diff_range_wrap (range);

	ret = data->hunk_cb (gdelta, grange, header, header_len,
	                     data->user_data);

	ggit_diff_range_unref (grange);
	ggit_diff_delta_unref (gdelta);

	return ret;
}

static gint
ggit_diff_line_callback_wrapper (const git_diff_delta *delta,
                                 const git_diff_range *range,
                                 gchar                 line_type,
                                 const gchar          *content,
                                 gsize                 content_len,
                                 gpointer              user_data)
{
	CallbackWrapperData *data = user_data;
	GgitDiffDelta *gdelta;
	GgitDiffRange *grange;
	gint ret;

	gdelta = _ggit_diff_delta_wrap (delta);
	grange = range == NULL ? NULL : _ggit_diff_range_wrap (range);

	ret = data->line_cb (gdelta, grange, (GgitDiffLineType) line_type,
	                     content, content_len, data->user_data);

	if (grange != NULL)
	{
		ggit_diff_range_unref (grange);
	}

	ggit_diff_delta_unref (gdelta);

	return ret;
}

static void
ggit_diff_class_init (GgitDiffClass *klass)
{
}

static void
ggit_diff_init (GgitDiff *self)
{
}

GgitDiff *
_ggit_diff_wrap (git_diff_list *diff,
                 gboolean       owned)
{
	GgitDiff *gdiff;

	gdiff = g_object_new (GGIT_TYPE_DIFF, NULL);
	_ggit_native_set (gdiff, diff, NULL);

	if (owned)
	{
		_ggit_native_set_destroy_func (gdiff,
		                               (GDestroyNotify)git_diff_list_free);
	}

	return gdiff;
}

/**
 * ggit_diff_new_tree_to_tree:
 * @repository: a #GgitRepository.
 * @old_tree: (allow-none): a #GgitTree to diff from.
 * @new_tree: (allow-none): a #GgitTree to diff to.
 * @diff_options: (allow-none): a #GgitDiffOptions, or %NULL.
 * @error: a #GError for error reporting, or %NULL.
 *
 * Creates a #GgitDiff which compares @old_tree and @new_tree.
 *
 * If @diff_options is %NULL then the defaults specified in
 * ggit_diff_options_new() are used.
 *
 * Returns: a newly allocated #GgitDiff if there was no error, %NULL otherwise.
 */
GgitDiff *
ggit_diff_new_tree_to_tree (GgitRepository   *repository,
                            GgitTree         *old_tree,
                            GgitTree         *new_tree,
                            GgitDiffOptions  *diff_options,
                            GError          **error)
{
	git_diff_list *diff;
	gint ret;

	g_return_val_if_fail (GGIT_IS_REPOSITORY (repository), NULL);
	g_return_val_if_fail (old_tree == NULL || GGIT_IS_TREE (old_tree), NULL);
	g_return_val_if_fail (new_tree == NULL || GGIT_IS_TREE (new_tree), NULL);
	g_return_val_if_fail (new_tree != NULL || new_tree != NULL, NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	ret = git_diff_tree_to_tree (&diff,
	                             _ggit_native_get (repository),
	                             old_tree ? _ggit_native_get (old_tree) : NULL,
	                             new_tree ? _ggit_native_get (new_tree) : NULL,
	                             _ggit_diff_options_get_diff_options (diff_options));

	if (ret != GIT_OK)
	{
		_ggit_error_set (error, ret);
		return NULL;
	}

	return _ggit_diff_wrap (diff, TRUE);
}

/**
 * ggit_diff_new_tree_to_index:
 * @repository: a #GgitRepository.
 * @old_tree: (allow-none): a #GgitTree to diff from.
 * @index: (allow-none): a #GgitIndex, or %NULL.
{'fraction_non_alphanumeric': 0.08831596269884805, 'fraction_numerical': 0.002011336624611446, 'mean_word_length': 2.4497004099653106, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6684879', 'n_tokens_mistral': 3666, 'n_tokens_neox': 3573, 'n_words': 910}