diff --git a/include/git2/sys/diff.h b/include/git2/sys/diff.h new file mode 100644 index 000000000..bc6cdf393 --- /dev/null +++ b/include/git2/sys/diff.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_sys_git_diff_h__ +#define INCLUDE_sys_git_diff_h__ + +#include "git2/common.h" +#include "git2/types.h" +#include "git2/oid.h" + +/** + * @file git2/sys/diff.h + * @brief Low-level Git diff utilities + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Diff print callback that writes to a git_buf. + * + * This function is provided not for you to call it directly, but instead + * so you can use it as a function pointer to the `git_diff_print` or + * `git_patch_print` APIs. When using those APIs, you specify a callback + * to actually handle the diff and/or patch data. + * + * Use this callback to easily write that data to a `git_buf` buffer. You + * must pass a `git_buf *` value as the payload to the `git_diff_print` + * and/or `git_patch_print` function. The data will be appended to the + * buffer (after any existing content). + */ +GIT_EXTERN(int) git_diff_print_callback__to_buf( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload); /*< payload must be a `git_buf *` */ + +/** + * Diff print callback that writes to stdio FILE handle. + * + * This function is provided not for you to call it directly, but instead + * so you can use it as a function pointer to the `git_diff_print` or + * `git_patch_print` APIs. When using those APIs, you specify a callback + * to actually handle the diff and/or patch data. + * + * Use this callback to easily write that data to a stdio FILE handle. You + * must pass a `FILE *` value (such as `stdout` or `stderr` or the return + * value from `fopen()`) as the payload to the `git_diff_print` + * and/or `git_patch_print` function. If you pass NULL, this will write + * data to `stdout`. + */ +GIT_EXTERN(int) git_diff_print_callback__to_file_handle( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload); /*< payload must be a `FILE *` */ + +/** @} */ +GIT_END_DECL +#endif diff --git a/src/diff_print.c b/src/diff_print.c index 1a09bed54..a7f7b6fe8 100644 --- a/src/diff_print.c +++ b/src/diff_print.c @@ -8,6 +8,7 @@ #include "diff.h" #include "diff_patch.h" #include "fileops.h" +#include "git2/sys/diff.h" typedef struct { git_diff *diff; @@ -435,7 +436,7 @@ int git_patch_print( return error; } -static int diff_print_to_buffer_cb( +int git_diff_print_callback__to_buf( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, @@ -444,6 +445,11 @@ static int diff_print_to_buffer_cb( git_buf *output = payload; GIT_UNUSED(delta); GIT_UNUSED(hunk); + if (!output) { + giterr_set(GITERR_INVALID, "Buffer pointer must be provided"); + return -1; + } + if (line->origin == GIT_DIFF_LINE_ADDITION || line->origin == GIT_DIFF_LINE_DELETION || line->origin == GIT_DIFF_LINE_CONTEXT) @@ -452,10 +458,28 @@ static int diff_print_to_buffer_cb( return git_buf_put(output, line->content, line->content_len); } +int git_diff_print_callback__to_file_handle( + const git_diff_delta *delta, + const git_diff_hunk *hunk, + const git_diff_line *line, + void *payload) +{ + FILE *fp = payload ? payload : stdout; + + GIT_UNUSED(delta); GIT_UNUSED(hunk); + + if (line->origin == GIT_DIFF_LINE_CONTEXT || + line->origin == GIT_DIFF_LINE_ADDITION || + line->origin == GIT_DIFF_LINE_DELETION) + fputc(line->origin, fp); + fwrite(line->content, 1, line->content_len, fp); + return 0; +} + /* print a git_patch to a git_buf */ int git_patch_to_buf( git_buf *out, git_patch *patch) { - return git_patch_print(patch, diff_print_to_buffer_cb, out); + return git_patch_print(patch, git_diff_print_callback__to_buf, out); } diff --git a/tests/diff/diff_helpers.c b/tests/diff/diff_helpers.c index 33bb561f6..279cb20c5 100644 --- a/tests/diff/diff_helpers.c +++ b/tests/diff/diff_helpers.c @@ -1,5 +1,6 @@ #include "clar_libgit2.h" #include "diff_helpers.h" +#include "git2/sys/diff.h" git_tree *resolve_commit_oid_to_tree( git_repository *repo, @@ -215,32 +216,16 @@ abort: return GIT_EUSER; } -static int diff_print_cb( - const git_diff_delta *delta, - const git_diff_hunk *hunk, - const git_diff_line *line, - void *payload) -{ - FILE *fp = payload; - - GIT_UNUSED(delta); GIT_UNUSED(hunk); - - if (line->origin == GIT_DIFF_LINE_CONTEXT || - line->origin == GIT_DIFF_LINE_ADDITION || - line->origin == GIT_DIFF_LINE_DELETION) - fputc(line->origin, fp); - fwrite(line->content, 1, line->content_len, fp); - return 0; -} - void diff_print(FILE *fp, git_diff *diff) { - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_PATCH, diff_print_cb, fp ? fp : stderr)); + cl_git_pass( + git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, + git_diff_print_callback__to_file_handle, fp ? fp : stderr)); } void diff_print_raw(FILE *fp, git_diff *diff) { - cl_git_pass(git_diff_print( - diff, GIT_DIFF_FORMAT_RAW, diff_print_cb, fp ? fp : stderr)); + cl_git_pass( + git_diff_print(diff, GIT_DIFF_FORMAT_RAW, + git_diff_print_callback__to_file_handle, fp ? fp : stderr)); }