Commit 27e54bcf by Russell Belfer

Add public diff print helpers

The usefulness of these helpers came up for me while debugging
some of the iterator changes that I was making, so since they
have also been requested (albeit indirectly) I thought I'd include
them.
parent 3dbee456
/*
* 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
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "diff.h" #include "diff.h"
#include "diff_patch.h" #include "diff_patch.h"
#include "fileops.h" #include "fileops.h"
#include "git2/sys/diff.h"
typedef struct { typedef struct {
git_diff *diff; git_diff *diff;
...@@ -435,7 +436,7 @@ int git_patch_print( ...@@ -435,7 +436,7 @@ int git_patch_print(
return error; return error;
} }
static int diff_print_to_buffer_cb( int git_diff_print_callback__to_buf(
const git_diff_delta *delta, const git_diff_delta *delta,
const git_diff_hunk *hunk, const git_diff_hunk *hunk,
const git_diff_line *line, const git_diff_line *line,
...@@ -444,6 +445,11 @@ static int diff_print_to_buffer_cb( ...@@ -444,6 +445,11 @@ static int diff_print_to_buffer_cb(
git_buf *output = payload; git_buf *output = payload;
GIT_UNUSED(delta); GIT_UNUSED(hunk); 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 || if (line->origin == GIT_DIFF_LINE_ADDITION ||
line->origin == GIT_DIFF_LINE_DELETION || line->origin == GIT_DIFF_LINE_DELETION ||
line->origin == GIT_DIFF_LINE_CONTEXT) line->origin == GIT_DIFF_LINE_CONTEXT)
...@@ -452,10 +458,28 @@ static int diff_print_to_buffer_cb( ...@@ -452,10 +458,28 @@ static int diff_print_to_buffer_cb(
return git_buf_put(output, line->content, line->content_len); 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 */ /* print a git_patch to a git_buf */
int git_patch_to_buf( int git_patch_to_buf(
git_buf *out, git_buf *out,
git_patch *patch) 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);
} }
#include "clar_libgit2.h" #include "clar_libgit2.h"
#include "diff_helpers.h" #include "diff_helpers.h"
#include "git2/sys/diff.h"
git_tree *resolve_commit_oid_to_tree( git_tree *resolve_commit_oid_to_tree(
git_repository *repo, git_repository *repo,
...@@ -215,32 +216,16 @@ abort: ...@@ -215,32 +216,16 @@ abort:
return GIT_EUSER; 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) void diff_print(FILE *fp, git_diff *diff)
{ {
cl_git_pass(git_diff_print( cl_git_pass(
diff, GIT_DIFF_FORMAT_PATCH, diff_print_cb, fp ? fp : stderr)); 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) void diff_print_raw(FILE *fp, git_diff *diff)
{ {
cl_git_pass(git_diff_print( cl_git_pass(
diff, GIT_DIFF_FORMAT_RAW, diff_print_cb, fp ? fp : stderr)); git_diff_print(diff, GIT_DIFF_FORMAT_RAW,
git_diff_print_callback__to_file_handle, fp ? fp : stderr));
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment