Commit 7000f3fa by Russell Belfer

Move some diff helpers into separate file

parent aad6967b
...@@ -207,6 +207,8 @@ static long diff_context_find( ...@@ -207,6 +207,8 @@ static long diff_context_find(
const char *scan; const char *scan;
bool found_paren = false; bool found_paren = false;
GIT_UNUSED(ctxt);
if (line_len > 0 && line[line_len - 1] == '\n') if (line_len > 0 && line[line_len - 1] == '\n')
line_len--; line_len--;
if (line_len > 0 && line[line_len - 1] == '\r') if (line_len > 0 && line[line_len - 1] == '\r')
...@@ -1064,359 +1066,6 @@ int git_diff_foreach( ...@@ -1064,359 +1066,6 @@ int git_diff_foreach(
return error; return error;
} }
typedef struct {
git_diff_list *diff;
git_diff_data_cb print_cb;
void *payload;
git_buf *buf;
int oid_strlen;
} diff_print_info;
static int diff_print_info_init(
diff_print_info *pi,
git_buf *out, git_diff_list *diff, git_diff_data_cb cb, void *payload)
{
assert(diff && diff->repo);
pi->diff = diff;
pi->print_cb = cb;
pi->payload = payload;
pi->buf = out;
if (git_repository__cvar(&pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0)
return -1;
pi->oid_strlen += 1; /* for NUL byte */
if (pi->oid_strlen < 2)
pi->oid_strlen = 2;
else if (pi->oid_strlen > GIT_OID_HEXSZ + 1)
pi->oid_strlen = GIT_OID_HEXSZ + 1;
return 0;
}
static char pick_suffix(int mode)
{
if (S_ISDIR(mode))
return '/';
else if (mode & 0100) //-V536
/* in git, modes are very regular, so we must have 0100755 mode */
return '*';
else
return ' ';
}
char git_diff_status_char(git_delta_t status)
{
char code;
switch (status) {
case GIT_DELTA_ADDED: code = 'A'; break;
case GIT_DELTA_DELETED: code = 'D'; break;
case GIT_DELTA_MODIFIED: code = 'M'; break;
case GIT_DELTA_RENAMED: code = 'R'; break;
case GIT_DELTA_COPIED: code = 'C'; break;
case GIT_DELTA_IGNORED: code = 'I'; break;
case GIT_DELTA_UNTRACKED: code = '?'; break;
default: code = ' '; break;
}
return code;
}
static int callback_error(void)
{
giterr_clear();
return GIT_EUSER;
}
static int print_compact(
const git_diff_delta *delta, float progress, void *data)
{
diff_print_info *pi = data;
char old_suffix, new_suffix, code = git_diff_status_char(delta->status);
GIT_UNUSED(progress);
if (code == ' ')
return 0;
old_suffix = pick_suffix(delta->old_file.mode);
new_suffix = pick_suffix(delta->new_file.mode);
git_buf_clear(pi->buf);
if (delta->old_file.path != delta->new_file.path &&
pi->diff->strcomp(delta->old_file.path,delta->new_file.path) != 0)
git_buf_printf(pi->buf, "%c\t%s%c -> %s%c\n", code,
delta->old_file.path, old_suffix, delta->new_file.path, new_suffix);
else if (delta->old_file.mode != delta->new_file.mode &&
delta->old_file.mode != 0 && delta->new_file.mode != 0)
git_buf_printf(pi->buf, "%c\t%s%c (%o -> %o)\n", code,
delta->old_file.path, new_suffix, delta->old_file.mode, delta->new_file.mode);
else if (old_suffix != ' ')
git_buf_printf(pi->buf, "%c\t%s%c\n", code, delta->old_file.path, old_suffix);
else
git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old_file.path);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
int git_diff_print_compact(
git_diff_list *diff,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf buf = GIT_BUF_INIT;
diff_print_info pi;
if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload)))
error = git_diff_foreach(diff, print_compact, NULL, NULL, &pi);
git_buf_free(&buf);
return error;
}
static int print_raw(
const git_diff_delta *delta, float progress, void *data)
{
diff_print_info *pi = data;
char code = git_diff_status_char(delta->status);
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
GIT_UNUSED(progress);
if (code == ' ')
return 0;
git_buf_clear(pi->buf);
git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid);
git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid);
git_buf_printf(
pi->buf, ":%06o %06o %s... %s... %c",
delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
if (delta->similarity > 0)
git_buf_printf(pi->buf, "%03u", delta->similarity);
if (delta->status == GIT_DELTA_RENAMED || delta->status == GIT_DELTA_COPIED)
git_buf_printf(
pi->buf, "\t%s %s\n", delta->old_file.path, delta->new_file.path);
else
git_buf_printf(
pi->buf, "\t%s\n", delta->old_file.path ?
delta->old_file.path : delta->new_file.path);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
int git_diff_print_raw(
git_diff_list *diff,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf buf = GIT_BUF_INIT;
diff_print_info pi;
if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload)))
error = git_diff_foreach(diff, print_raw, NULL, NULL, &pi);
git_buf_free(&buf);
return error;
}
static int print_oid_range(diff_print_info *pi, const git_diff_delta *delta)
{
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid);
git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid);
/* TODO: Match git diff more closely */
if (delta->old_file.mode == delta->new_file.mode) {
git_buf_printf(pi->buf, "index %s..%s %o\n",
start_oid, end_oid, delta->old_file.mode);
} else {
if (delta->old_file.mode == 0) {
git_buf_printf(pi->buf, "new file mode %o\n", delta->new_file.mode);
} else if (delta->new_file.mode == 0) {
git_buf_printf(pi->buf, "deleted file mode %o\n", delta->old_file.mode);
} else {
git_buf_printf(pi->buf, "old mode %o\n", delta->old_file.mode);
git_buf_printf(pi->buf, "new mode %o\n", delta->new_file.mode);
}
git_buf_printf(pi->buf, "index %s..%s\n", start_oid, end_oid);
}
if (git_buf_oom(pi->buf))
return -1;
return 0;
}
static int print_patch_file(
const git_diff_delta *delta, float progress, void *data)
{
diff_print_info *pi = data;
const char *oldpfx = pi->diff->opts.old_prefix;
const char *oldpath = delta->old_file.path;
const char *newpfx = pi->diff->opts.new_prefix;
const char *newpath = delta->new_file.path;
GIT_UNUSED(progress);
if (S_ISDIR(delta->new_file.mode) ||
delta->status == GIT_DELTA_UNMODIFIED ||
delta->status == GIT_DELTA_IGNORED ||
(delta->status == GIT_DELTA_UNTRACKED &&
(pi->diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0))
return 0;
if (!oldpfx)
oldpfx = DIFF_OLD_PREFIX_DEFAULT;
if (!newpfx)
newpfx = DIFF_NEW_PREFIX_DEFAULT;
git_buf_clear(pi->buf);
git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old_file.path, newpfx, delta->new_file.path);
if (print_oid_range(pi, delta) < 0)
return -1;
if (git_oid_iszero(&delta->old_file.oid)) {
oldpfx = "";
oldpath = "/dev/null";
}
if (git_oid_iszero(&delta->new_file.oid)) {
newpfx = "";
newpath = "/dev/null";
}
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) {
git_buf_printf(pi->buf, "--- %s%s\n", oldpfx, oldpath);
git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath);
}
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
return 0;
git_buf_clear(pi->buf);
git_buf_printf(
pi->buf, "Binary files %s%s and %s%s differ\n",
oldpfx, oldpath, newpfx, newpath);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
static int print_patch_hunk(
const git_diff_delta *d,
const git_diff_range *r,
const char *header,
size_t header_len,
void *data)
{
diff_print_info *pi = data;
if (S_ISDIR(d->new_file.mode))
return 0;
git_buf_clear(pi->buf);
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
return -1;
if (pi->print_cb(d, r, GIT_DIFF_LINE_HUNK_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
static int print_patch_line(
const git_diff_delta *delta,
const git_diff_range *range,
char line_origin, /* GIT_DIFF_LINE value from above */
const char *content,
size_t content_len,
void *data)
{
diff_print_info *pi = data;
if (S_ISDIR(delta->new_file.mode))
return 0;
git_buf_clear(pi->buf);
if (line_origin == GIT_DIFF_LINE_ADDITION ||
line_origin == GIT_DIFF_LINE_DELETION ||
line_origin == GIT_DIFF_LINE_CONTEXT)
git_buf_printf(pi->buf, "%c%.*s", line_origin, (int)content_len, content);
else if (content_len > 0)
git_buf_printf(pi->buf, "%.*s", (int)content_len, content);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, range, line_origin,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
int git_diff_print_patch(
git_diff_list *diff,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf buf = GIT_BUF_INIT;
diff_print_info pi;
if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload)))
error = git_diff_foreach(
diff, print_patch_file, print_patch_hunk, print_patch_line, &pi);
git_buf_free(&buf);
return error;
}
static void set_data_from_blob( static void set_data_from_blob(
const git_blob *blob, git_map *map, git_diff_file *file) const git_blob *blob, git_map *map, git_diff_file *file)
{ {
...@@ -1826,75 +1475,6 @@ notfound: ...@@ -1826,75 +1475,6 @@ notfound:
return diff_error_outofrange(thing); return diff_error_outofrange(thing);
} }
static int print_to_buffer_cb(
const git_diff_delta *delta,
const git_diff_range *range,
char line_origin,
const char *content,
size_t content_len,
void *payload)
{
git_buf *output = payload;
GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(line_origin);
return git_buf_put(output, content, content_len);
}
int git_diff_patch_print(
git_diff_patch *patch,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf temp = GIT_BUF_INIT;
diff_print_info pi;
size_t h, l;
assert(patch && print_cb);
if (!(error = diff_print_info_init(
&pi, &temp, patch->diff, print_cb, payload)))
error = print_patch_file(patch->delta, 0, &pi);
for (h = 0; h < patch->hunks_size && !error; ++h) {
diff_patch_hunk *hunk = &patch->hunks[h];
error = print_patch_hunk(
patch->delta, &hunk->range, hunk->header, hunk->header_len, &pi);
for (l = 0; l < hunk->line_count && !error; ++l) {
diff_patch_line *line = &patch->lines[hunk->line_start + l];
error = print_patch_line(
patch->delta, &hunk->range,
line->origin, line->ptr, line->len, &pi);
}
}
git_buf_free(&temp);
return error;
}
int git_diff_patch_to_str(
char **string,
git_diff_patch *patch)
{
int error;
git_buf output = GIT_BUF_INIT;
error = git_diff_patch_print(patch, print_to_buffer_cb, &output);
/* GIT_EUSER means git_buf_put in print_to_buffer_cb returned -1,
* meaning a memory allocation failure, so just map to -1...
*/
if (error == GIT_EUSER)
error = -1;
*string = git_buf_detach(&output);
return error;
}
int git_diff__paired_foreach( int git_diff__paired_foreach(
git_diff_list *idx2head, git_diff_list *idx2head,
git_diff_list *wd2idx, git_diff_list *wd2idx,
......
/*
* 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.
*/
#include "common.h"
#include "diff.h"
#include "diff_output.h"
typedef struct {
git_diff_list *diff;
git_diff_data_cb print_cb;
void *payload;
git_buf *buf;
int oid_strlen;
} diff_print_info;
static int diff_print_info_init(
diff_print_info *pi,
git_buf *out, git_diff_list *diff, git_diff_data_cb cb, void *payload)
{
assert(diff && diff->repo);
pi->diff = diff;
pi->print_cb = cb;
pi->payload = payload;
pi->buf = out;
if (git_repository__cvar(&pi->oid_strlen, diff->repo, GIT_CVAR_ABBREV) < 0)
return -1;
pi->oid_strlen += 1; /* for NUL byte */
if (pi->oid_strlen < 2)
pi->oid_strlen = 2;
else if (pi->oid_strlen > GIT_OID_HEXSZ + 1)
pi->oid_strlen = GIT_OID_HEXSZ + 1;
return 0;
}
static char pick_suffix(int mode)
{
if (S_ISDIR(mode))
return '/';
else if (mode & 0100) //-V536
/* in git, modes are very regular, so we must have 0100755 mode */
return '*';
else
return ' ';
}
char git_diff_status_char(git_delta_t status)
{
char code;
switch (status) {
case GIT_DELTA_ADDED: code = 'A'; break;
case GIT_DELTA_DELETED: code = 'D'; break;
case GIT_DELTA_MODIFIED: code = 'M'; break;
case GIT_DELTA_RENAMED: code = 'R'; break;
case GIT_DELTA_COPIED: code = 'C'; break;
case GIT_DELTA_IGNORED: code = 'I'; break;
case GIT_DELTA_UNTRACKED: code = '?'; break;
default: code = ' '; break;
}
return code;
}
static int callback_error(void)
{
giterr_clear();
return GIT_EUSER;
}
static int print_compact(
const git_diff_delta *delta, float progress, void *data)
{
diff_print_info *pi = data;
char old_suffix, new_suffix, code = git_diff_status_char(delta->status);
GIT_UNUSED(progress);
if (code == ' ')
return 0;
old_suffix = pick_suffix(delta->old_file.mode);
new_suffix = pick_suffix(delta->new_file.mode);
git_buf_clear(pi->buf);
if (delta->old_file.path != delta->new_file.path &&
pi->diff->strcomp(delta->old_file.path,delta->new_file.path) != 0)
git_buf_printf(pi->buf, "%c\t%s%c -> %s%c\n", code,
delta->old_file.path, old_suffix, delta->new_file.path, new_suffix);
else if (delta->old_file.mode != delta->new_file.mode &&
delta->old_file.mode != 0 && delta->new_file.mode != 0)
git_buf_printf(pi->buf, "%c\t%s%c (%o -> %o)\n", code,
delta->old_file.path, new_suffix, delta->old_file.mode, delta->new_file.mode);
else if (old_suffix != ' ')
git_buf_printf(pi->buf, "%c\t%s%c\n", code, delta->old_file.path, old_suffix);
else
git_buf_printf(pi->buf, "%c\t%s\n", code, delta->old_file.path);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
int git_diff_print_compact(
git_diff_list *diff,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf buf = GIT_BUF_INIT;
diff_print_info pi;
if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload)))
error = git_diff_foreach(diff, print_compact, NULL, NULL, &pi);
git_buf_free(&buf);
return error;
}
static int print_raw(
const git_diff_delta *delta, float progress, void *data)
{
diff_print_info *pi = data;
char code = git_diff_status_char(delta->status);
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
GIT_UNUSED(progress);
if (code == ' ')
return 0;
git_buf_clear(pi->buf);
git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid);
git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid);
git_buf_printf(
pi->buf, ":%06o %06o %s... %s... %c",
delta->old_file.mode, delta->new_file.mode, start_oid, end_oid, code);
if (delta->similarity > 0)
git_buf_printf(pi->buf, "%03u", delta->similarity);
if (delta->status == GIT_DELTA_RENAMED || delta->status == GIT_DELTA_COPIED)
git_buf_printf(
pi->buf, "\t%s %s\n", delta->old_file.path, delta->new_file.path);
else
git_buf_printf(
pi->buf, "\t%s\n", delta->old_file.path ?
delta->old_file.path : delta->new_file.path);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
int git_diff_print_raw(
git_diff_list *diff,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf buf = GIT_BUF_INIT;
diff_print_info pi;
if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload)))
error = git_diff_foreach(diff, print_raw, NULL, NULL, &pi);
git_buf_free(&buf);
return error;
}
static int print_oid_range(diff_print_info *pi, const git_diff_delta *delta)
{
char start_oid[GIT_OID_HEXSZ+1], end_oid[GIT_OID_HEXSZ+1];
git_oid_tostr(start_oid, pi->oid_strlen, &delta->old_file.oid);
git_oid_tostr(end_oid, pi->oid_strlen, &delta->new_file.oid);
/* TODO: Match git diff more closely */
if (delta->old_file.mode == delta->new_file.mode) {
git_buf_printf(pi->buf, "index %s..%s %o\n",
start_oid, end_oid, delta->old_file.mode);
} else {
if (delta->old_file.mode == 0) {
git_buf_printf(pi->buf, "new file mode %o\n", delta->new_file.mode);
} else if (delta->new_file.mode == 0) {
git_buf_printf(pi->buf, "deleted file mode %o\n", delta->old_file.mode);
} else {
git_buf_printf(pi->buf, "old mode %o\n", delta->old_file.mode);
git_buf_printf(pi->buf, "new mode %o\n", delta->new_file.mode);
}
git_buf_printf(pi->buf, "index %s..%s\n", start_oid, end_oid);
}
if (git_buf_oom(pi->buf))
return -1;
return 0;
}
static int print_patch_file(
const git_diff_delta *delta, float progress, void *data)
{
diff_print_info *pi = data;
const char *oldpfx = pi->diff->opts.old_prefix;
const char *oldpath = delta->old_file.path;
const char *newpfx = pi->diff->opts.new_prefix;
const char *newpath = delta->new_file.path;
GIT_UNUSED(progress);
if (S_ISDIR(delta->new_file.mode) ||
delta->status == GIT_DELTA_UNMODIFIED ||
delta->status == GIT_DELTA_IGNORED ||
(delta->status == GIT_DELTA_UNTRACKED &&
(pi->diff->opts.flags & GIT_DIFF_INCLUDE_UNTRACKED_CONTENT) == 0))
return 0;
if (!oldpfx)
oldpfx = DIFF_OLD_PREFIX_DEFAULT;
if (!newpfx)
newpfx = DIFF_NEW_PREFIX_DEFAULT;
git_buf_clear(pi->buf);
git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->old_file.path, newpfx, delta->new_file.path);
if (print_oid_range(pi, delta) < 0)
return -1;
if (git_oid_iszero(&delta->old_file.oid)) {
oldpfx = "";
oldpath = "/dev/null";
}
if (git_oid_iszero(&delta->new_file.oid)) {
newpfx = "";
newpath = "/dev/null";
}
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0) {
git_buf_printf(pi->buf, "--- %s%s\n", oldpfx, oldpath);
git_buf_printf(pi->buf, "+++ %s%s\n", newpfx, newpath);
}
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_FILE_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
if ((delta->flags & GIT_DIFF_FLAG_BINARY) == 0)
return 0;
git_buf_clear(pi->buf);
git_buf_printf(
pi->buf, "Binary files %s%s and %s%s differ\n",
oldpfx, oldpath, newpfx, newpath);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, NULL, GIT_DIFF_LINE_BINARY,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
static int print_patch_hunk(
const git_diff_delta *d,
const git_diff_range *r,
const char *header,
size_t header_len,
void *data)
{
diff_print_info *pi = data;
if (S_ISDIR(d->new_file.mode))
return 0;
git_buf_clear(pi->buf);
if (git_buf_printf(pi->buf, "%.*s", (int)header_len, header) < 0)
return -1;
if (pi->print_cb(d, r, GIT_DIFF_LINE_HUNK_HDR,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
static int print_patch_line(
const git_diff_delta *delta,
const git_diff_range *range,
char line_origin, /* GIT_DIFF_LINE value from above */
const char *content,
size_t content_len,
void *data)
{
diff_print_info *pi = data;
if (S_ISDIR(delta->new_file.mode))
return 0;
git_buf_clear(pi->buf);
if (line_origin == GIT_DIFF_LINE_ADDITION ||
line_origin == GIT_DIFF_LINE_DELETION ||
line_origin == GIT_DIFF_LINE_CONTEXT)
git_buf_printf(pi->buf, "%c%.*s", line_origin, (int)content_len, content);
else if (content_len > 0)
git_buf_printf(pi->buf, "%.*s", (int)content_len, content);
if (git_buf_oom(pi->buf))
return -1;
if (pi->print_cb(delta, range, line_origin,
git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload))
return callback_error();
return 0;
}
int git_diff_print_patch(
git_diff_list *diff,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf buf = GIT_BUF_INIT;
diff_print_info pi;
if (!(error = diff_print_info_init(&pi, &buf, diff, print_cb, payload)))
error = git_diff_foreach(
diff, print_patch_file, print_patch_hunk, print_patch_line, &pi);
git_buf_free(&buf);
return error;
}
static int print_to_buffer_cb(
const git_diff_delta *delta,
const git_diff_range *range,
char line_origin,
const char *content,
size_t content_len,
void *payload)
{
git_buf *output = payload;
GIT_UNUSED(delta); GIT_UNUSED(range); GIT_UNUSED(line_origin);
return git_buf_put(output, content, content_len);
}
int git_diff_patch_print(
git_diff_patch *patch,
git_diff_data_cb print_cb,
void *payload)
{
int error;
git_buf temp = GIT_BUF_INIT;
diff_print_info pi;
size_t h, l;
assert(patch && print_cb);
if (!(error = diff_print_info_init(
&pi, &temp, patch->diff, print_cb, payload)))
error = print_patch_file(patch->delta, 0, &pi);
for (h = 0; h < patch->hunks_size && !error; ++h) {
diff_patch_hunk *hunk = &patch->hunks[h];
error = print_patch_hunk(
patch->delta, &hunk->range, hunk->header, hunk->header_len, &pi);
for (l = 0; l < hunk->line_count && !error; ++l) {
diff_patch_line *line = &patch->lines[hunk->line_start + l];
error = print_patch_line(
patch->delta, &hunk->range,
line->origin, line->ptr, line->len, &pi);
}
}
git_buf_free(&temp);
return error;
}
int git_diff_patch_to_str(
char **string,
git_diff_patch *patch)
{
int error;
git_buf output = GIT_BUF_INIT;
error = git_diff_patch_print(patch, print_to_buffer_cb, &output);
/* GIT_EUSER means git_buf_put in print_to_buffer_cb returned -1,
* meaning a memory allocation failure, so just map to -1...
*/
if (error == GIT_EUSER)
error = -1;
*string = git_buf_detach(&output);
return error;
}
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