Commit d4723c89 by Carlos Martín Nieto

Merge pull request #3177 from ethomson/binary_diff

Binary diffs: store deltas in the diff structure, include binary data in diff callbacks
parents ae22ef0e 0e522f6e
......@@ -65,6 +65,10 @@ support for HTTPS connections insead of OpenSSL.
configuration. This allows modifying URL prefixes to a custom
value via gitconfig.
* `git_diff_foreach`, `git_diff_blobs`, `git_diff_blob_to_buffer`,
and `git_diff_buffers` now accept a new binary callback of type
`git_diff_binary_cb` that includes the binary diff information.
### API additions
* The `git_merge_options` gained a `file_flags` member.
......
......@@ -426,6 +426,53 @@ typedef int (*git_diff_file_cb)(
void *payload);
/**
* When producing a binary diff, the binary data returned will be
* either the deflated full ("literal") contents of the file, or
* the deflated binary delta between the two sides (whichever is
* smaller).
*/
typedef enum {
/** There is no binary delta. */
GIT_DIFF_BINARY_NONE,
/** The binary data is the literal contents of the file. */
GIT_DIFF_BINARY_LITERAL,
/** The binary data is the delta from one side to the other. */
GIT_DIFF_BINARY_DELTA,
} git_diff_binary_t;
/** The contents of one of the files in a binary diff. */
typedef struct {
/** The type of binary data for this file. */
git_diff_binary_t type;
/** The binary data, deflated. */
const char *data;
/** The length of the binary data. */
size_t datalen;
/** The length of the binary data after inflation. */
size_t inflatedlen;
} git_diff_binary_file;
/** Structure describing the binary contents of a diff. */
typedef struct {
git_diff_binary_file old_file; /**< The contents of the old file. */
git_diff_binary_file new_file; /**< The contents of the new file. */
} git_diff_binary;
/**
* When iterating over a diff, callback that will be made for
* binary content within the diff.
*/
typedef int(*git_diff_binary_cb)(
const git_diff_delta *delta,
const git_diff_binary *binary,
void *payload);
/**
* Structure describing a hunk of a diff.
*/
typedef struct {
......@@ -897,6 +944,7 @@ GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff);
*
* @param diff A git_diff generated by one of the above functions.
* @param file_cb Callback function to make per file in the diff.
* @param binary_cb Optional callback to make for binary files.
* @param hunk_cb Optional callback to make per hunk of text diff. This
* callback is called to describe a range of lines in the
* diff. It will not be issued for binary files.
......@@ -909,6 +957,7 @@ GIT_EXTERN(int) git_diff_is_sorted_icase(const git_diff *diff);
GIT_EXTERN(int) git_diff_foreach(
git_diff *diff,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *payload);
......@@ -984,6 +1033,7 @@ GIT_EXTERN(int) git_diff_print(
* @param new_as_path Treat new blob as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options
* @param file_cb Callback for "file"; made once if there is a diff; can be NULL
* @param binary_cb Callback for binary files; can be NULL
* @param hunk_cb Callback for each hunk in diff; can be NULL
* @param line_cb Callback for each line in diff; can be NULL
* @param payload Payload passed to each callback function
......@@ -996,6 +1046,7 @@ GIT_EXTERN(int) git_diff_blobs(
const char *new_as_path,
const git_diff_options *options,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *payload);
......@@ -1019,6 +1070,7 @@ GIT_EXTERN(int) git_diff_blobs(
* @param buffer_as_path Treat buffer as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options
* @param file_cb Callback for "file"; made once if there is a diff; can be NULL
* @param binary_cb Callback for binary files; can be NULL
* @param hunk_cb Callback for each hunk in diff; can be NULL
* @param line_cb Callback for each line in diff; can be NULL
* @param payload Payload passed to each callback function
......@@ -1032,6 +1084,7 @@ GIT_EXTERN(int) git_diff_blob_to_buffer(
const char *buffer_as_path,
const git_diff_options *options,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *payload);
......@@ -1051,6 +1104,7 @@ GIT_EXTERN(int) git_diff_blob_to_buffer(
* @param new_as_path Treat buffer as if it had this filename; can be NULL
* @param options Options for diff, or NULL for default options
* @param file_cb Callback for "file"; made once if there is a diff; can be NULL
* @param binary_cb Callback for binary files; can be NULL
* @param hunk_cb Callback for each hunk in diff; can be NULL
* @param line_cb Callback for each line in diff; can be NULL
* @param payload Payload passed to each callback function
......@@ -1065,6 +1119,7 @@ GIT_EXTERN(int) git_diff_buffers(
const char *new_as_path,
const git_diff_options *options,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *payload);
......
......@@ -496,8 +496,8 @@ int git_blame_buffer(
/* Diff to the reference blob */
git_diff_blob_to_buffer(reference->final_blob, blame->path,
buffer, buffer_len, blame->path,
&diffopts, NULL, buffer_hunk_cb, buffer_line_cb, blame);
buffer, buffer_len, blame->path, &diffopts,
NULL, NULL, buffer_hunk_cb, buffer_line_cb, blame);
*out = blame;
return 0;
......
......@@ -89,10 +89,9 @@ static int diff_file_content_init_common(
int git_diff_file_content__init_from_diff(
git_diff_file_content *fc,
git_diff *diff,
size_t delta_index,
git_diff_delta *delta,
bool use_old)
{
git_diff_delta *delta = git_vector_get(&diff->deltas, delta_index);
bool has_data = true;
memset(fc, 0, sizeof(*fc));
......@@ -218,7 +217,9 @@ static int diff_file_content_commit_to_str(
return 0;
}
static int diff_file_content_load_blob(git_diff_file_content *fc)
static int diff_file_content_load_blob(
git_diff_file_content *fc,
git_diff_options *opts)
{
int error = 0;
git_odb_object *odb_obj = NULL;
......@@ -236,7 +237,8 @@ static int diff_file_content_load_blob(git_diff_file_content *fc)
return error;
}
if (diff_file_content_binary_by_size(fc))
if ((opts->flags & GIT_DIFF_SHOW_BINARY) == 0 &&
diff_file_content_binary_by_size(fc))
return 0;
if (odb_obj != NULL) {
......@@ -283,7 +285,9 @@ static int diff_file_content_load_workdir_symlink(
}
static int diff_file_content_load_workdir_file(
git_diff_file_content *fc, git_buf *path)
git_diff_file_content *fc,
git_buf *path,
git_diff_options *diff_opts)
{
int error = 0;
git_filter_list *fl = NULL;
......@@ -297,7 +301,8 @@ static int diff_file_content_load_workdir_file(
!(fc->file->size = git_futils_filesize(fd)))
goto cleanup;
if (diff_file_content_binary_by_size(fc))
if ((diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0 &&
diff_file_content_binary_by_size(fc))
goto cleanup;
if ((error = git_filter_list_load(
......@@ -339,7 +344,9 @@ cleanup:
return error;
}
static int diff_file_content_load_workdir(git_diff_file_content *fc)
static int diff_file_content_load_workdir(
git_diff_file_content *fc,
git_diff_options *diff_opts)
{
int error = 0;
git_buf path = GIT_BUF_INIT;
......@@ -357,7 +364,7 @@ static int diff_file_content_load_workdir(git_diff_file_content *fc)
if (S_ISLNK(fc->file->mode))
error = diff_file_content_load_workdir_symlink(fc, &path);
else
error = diff_file_content_load_workdir_file(fc, &path);
error = diff_file_content_load_workdir_file(fc, &path, diff_opts);
/* once data is loaded, update OID if we didn't have it previously */
if (!error && (fc->file->flags & GIT_DIFF_FLAG_VALID_ID) == 0) {
......@@ -370,20 +377,23 @@ static int diff_file_content_load_workdir(git_diff_file_content *fc)
return error;
}
int git_diff_file_content__load(git_diff_file_content *fc)
int git_diff_file_content__load(
git_diff_file_content *fc,
git_diff_options *diff_opts)
{
int error = 0;
if ((fc->flags & GIT_DIFF_FLAG__LOADED) != 0)
return 0;
if ((fc->file->flags & GIT_DIFF_FLAG_BINARY) != 0)
if ((fc->file->flags & GIT_DIFF_FLAG_BINARY) != 0 &&
(diff_opts->flags & GIT_DIFF_SHOW_BINARY) == 0)
return 0;
if (fc->src == GIT_ITERATOR_TYPE_WORKDIR)
error = diff_file_content_load_workdir(fc);
error = diff_file_content_load_workdir(fc, diff_opts);
else
error = diff_file_content_load_blob(fc);
error = diff_file_content_load_blob(fc, diff_opts);
if (error)
return error;
......
......@@ -28,7 +28,7 @@ typedef struct {
extern int git_diff_file_content__init_from_diff(
git_diff_file_content *fc,
git_diff *diff,
size_t delta_index,
git_diff_delta *delta,
bool use_old);
typedef struct {
......@@ -49,7 +49,9 @@ extern int git_diff_file_content__init_from_src(
git_diff_file *as_file);
/* this loads the blob/file-on-disk as needed */
extern int git_diff_file_content__load(git_diff_file_content *fc);
extern int git_diff_file_content__load(
git_diff_file_content *fc,
git_diff_options *diff_opts);
/* this releases the blob/file-in-memory */
extern void git_diff_file_content__unload(git_diff_file_content *fc);
......
......@@ -13,6 +13,38 @@
#include "array.h"
#include "git2/patch.h"
/* cached information about a hunk in a diff */
typedef struct diff_patch_hunk {
git_diff_hunk hunk;
size_t line_start;
size_t line_count;
} diff_patch_hunk;
enum {
GIT_DIFF_PATCH_ALLOCATED = (1 << 0),
GIT_DIFF_PATCH_INITIALIZED = (1 << 1),
GIT_DIFF_PATCH_LOADED = (1 << 2),
GIT_DIFF_PATCH_DIFFABLE = (1 << 3),
GIT_DIFF_PATCH_DIFFED = (1 << 4),
GIT_DIFF_PATCH_FLATTENED = (1 << 5),
};
struct git_patch {
git_refcount rc;
git_diff *diff; /* for refcount purposes, maybe NULL for blob diffs */
git_diff_options diff_opts;
git_diff_delta *delta;
size_t delta_index;
git_diff_file_content ofile;
git_diff_file_content nfile;
uint32_t flags;
git_diff_binary binary;
git_array_t(diff_patch_hunk) hunks;
git_array_t(git_diff_line) lines;
size_t content_size, context_size, header_size;
git_pool flattened;
};
extern git_diff *git_patch__diff(git_patch *);
extern git_diff_driver *git_patch__driver(git_patch *);
......@@ -23,6 +55,7 @@ extern void git_patch__new_data(char **, size_t *, git_patch *);
extern int git_patch__invoke_callbacks(
git_patch *patch,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *payload);
......@@ -31,6 +64,7 @@ typedef struct git_diff_output git_diff_output;
struct git_diff_output {
/* these callbacks are issued with the diff data */
git_diff_file_cb file_cb;
git_diff_binary_cb binary_cb;
git_diff_hunk_cb hunk_cb;
git_diff_line_cb data_cb;
void *payload;
......
......@@ -2727,7 +2727,7 @@ static int index_apply_to_wd_diff(git_index *index, int action, const git_strarr
goto cleanup;
data.pathspec = &ps;
error = git_diff_foreach(diff, apply_each_file, NULL, NULL, &data);
error = git_diff_foreach(diff, apply_each_file, NULL, NULL, NULL, &data);
git_diff_free(diff);
if (error) /* make sure error is set if callback stopped iteration */
......
......@@ -261,3 +261,232 @@ void test_diff_binary__delta_append(void)
git_index_free(index);
}
void test_diff_binary__index_to_workdir(void)
{
git_index *index;
git_diff *diff;
git_patch *patch;
git_buf actual = GIT_BUF_INIT;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
const char *expected =
"diff --git a/untimely.txt b/untimely.txt\n" \
"index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \
"GIT binary patch\n" \
"delta 32\n" \
"nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
"\n" \
"delta 7\n" \
"Oc%18D`@*{63ljhg(E~C7\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
repo = cl_git_sandbox_init("renames");
cl_git_pass(git_repository_index(&index, repo));
cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
cl_git_pass(git_diff_index_to_workdir(&diff, repo, index, &opts));
cl_git_pass(git_patch_from_diff(&patch, diff, 0));
cl_git_pass(git_patch_to_buf(&actual, patch));
cl_assert_equal_s(expected, actual.ptr);
cl_git_pass(git_index_add_bypath(index, "untimely.txt"));
cl_git_pass(git_index_write(index));
test_patch(
"19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13",
NULL,
&opts,
expected);
git_buf_free(&actual);
git_patch_free(patch);
git_diff_free(diff);
git_index_free(index);
}
static int print_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *payload)
{
git_buf *buf = (git_buf *)payload;
if (hunk)
git_buf_put(buf, hunk->header, hunk->header_len);
if (line)
git_buf_put(buf, line->content, line->content_len);
return git_buf_oom(buf) ? -1 : 0;
}
void test_diff_binary__print_patch_from_diff(void)
{
git_index *index;
git_diff *diff;
git_buf actual = GIT_BUF_INIT;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
const char *expected =
"diff --git a/untimely.txt b/untimely.txt\n" \
"index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \
"GIT binary patch\n" \
"delta 32\n" \
"nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
"\n" \
"delta 7\n" \
"Oc%18D`@*{63ljhg(E~C7\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
repo = cl_git_sandbox_init("renames");
cl_git_pass(git_repository_index(&index, repo));
cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
cl_git_pass(git_diff_index_to_workdir(&diff, repo, index, &opts));
cl_git_pass(git_diff_print(diff, GIT_DIFF_FORMAT_PATCH, print_cb, &actual));
cl_assert_equal_s(expected, actual.ptr);
git_buf_free(&actual);
git_diff_free(diff);
git_index_free(index);
}
struct diff_data {
char *old_path;
git_oid old_id;
git_buf old_binary_base85;
size_t old_binary_inflatedlen;
git_diff_binary_t old_binary_type;
char *new_path;
git_oid new_id;
git_buf new_binary_base85;
size_t new_binary_inflatedlen;
git_diff_binary_t new_binary_type;
};
static int file_cb(
const git_diff_delta *delta,
float progress,
void *payload)
{
struct diff_data *diff_data = payload;
if (delta->old_file.path)
diff_data->old_path = git__strdup(delta->old_file.path);
if (delta->new_file.path)
diff_data->new_path = git__strdup(delta->new_file.path);
git_oid_cpy(&diff_data->old_id, &delta->old_file.id);
git_oid_cpy(&diff_data->new_id, &delta->new_file.id);
return 0;
}
static int binary_cb(
const git_diff_delta *delta,
const git_diff_binary *binary,
void *payload)
{
struct diff_data *diff_data = payload;
git_buf_encode_base85(&diff_data->old_binary_base85,
binary->old_file.data, binary->old_file.datalen);
diff_data->old_binary_inflatedlen = binary->old_file.inflatedlen;
diff_data->old_binary_type = binary->old_file.type;
git_buf_encode_base85(&diff_data->new_binary_base85,
binary->new_file.data, binary->new_file.datalen);
diff_data->new_binary_inflatedlen = binary->new_file.inflatedlen;
diff_data->new_binary_type = binary->new_file.type;
return 0;
}
static int hunk_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk,
void *payload)
{
cl_fail("did not expect hunk callback");
return 0;
}
static int line_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk,
const git_diff_line *line,
void *payload)
{
cl_fail("did not expect line callback");
return 0;
}
void test_diff_binary__blob_to_blob(void)
{
git_index *index;
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
git_blob *old_blob, *new_blob;
git_oid old_id, new_id;
struct diff_data diff_data = {0};
const char *expected =
"diff --git a/untimely.txt b/untimely.txt\n" \
"index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \
"GIT binary patch\n" \
"delta 32\n" \
"nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
"\n" \
"delta 7\n" \
"Oc%18D`@*{63ljhg(E~C7\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
repo = cl_git_sandbox_init("renames");
cl_git_pass(git_repository_index(&index, repo));
cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n");
cl_git_pass(git_index_add_bypath(index, "untimely.txt"));
cl_git_pass(git_index_write(index));
git_oid_fromstr(&old_id, "9a69d960ae94b060f56c2a8702545e2bb1abb935");
git_oid_fromstr(&new_id, "1111d4f11f4b35bf6759e0fb714fe09731ef0840");
cl_git_pass(git_blob_lookup(&old_blob, repo, &old_id));
cl_git_pass(git_blob_lookup(&new_blob, repo, &new_id));
cl_git_pass(git_diff_blobs(old_blob,
"untimely.txt", new_blob, "untimely.txt", &opts,
file_cb, binary_cb, hunk_cb, line_cb, &diff_data));
cl_assert_equal_s("untimely.txt", diff_data.old_path);
cl_assert_equal_oid(&old_id, &diff_data.old_id);
cl_assert_equal_i(GIT_DIFF_BINARY_DELTA, diff_data.old_binary_type);
cl_assert_equal_i(7, diff_data.old_binary_inflatedlen);
cl_assert_equal_s("c%18D`@*{63ljhg(E~C7",
diff_data.old_binary_base85.ptr);
cl_assert_equal_s("untimely.txt", diff_data.new_path);
cl_assert_equal_oid(&new_id, &diff_data.new_id);
cl_assert_equal_i(GIT_DIFF_BINARY_DELTA, diff_data.new_binary_type);
cl_assert_equal_i(32, diff_data.new_binary_inflatedlen);
cl_assert_equal_s("c%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW",
diff_data.new_binary_base85.ptr);
git_blob_free(old_blob);
git_blob_free(new_blob);
git__free(diff_data.old_path);
git__free(diff_data.new_path);
}
......@@ -17,7 +17,7 @@ static void quick_diff_blob_to_str(
cl_git_pass(git_diff_blob_to_buffer(
blob, blob_path, str, len, str_path,
&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
&opts, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
}
void test_diff_blob__initialize(void)
......@@ -88,7 +88,7 @@ void test_diff_blob__can_compare_text_blobs(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
a, NULL, b, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(1, 6, 1, 5, 0, &expected);
/* same diff but use direct buffers */
......@@ -96,27 +96,27 @@ void test_diff_blob__can_compare_text_blobs(void)
cl_git_pass(git_diff_buffers(
git_blob_rawcontent(a), (size_t)git_blob_rawsize(a), NULL,
git_blob_rawcontent(b), (size_t)git_blob_rawsize(b), NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(1, 6, 1, 5, 0, &expected);
/* diff on tests/resources/attr/root_test2 */
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
b, NULL, c, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(1, 15, 3, 9, 3, &expected);
/* diff on tests/resources/attr/root_test3 */
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
a, NULL, c, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(1, 13, 0, 12, 1, &expected);
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
c, NULL, d, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(2, 14, 4, 6, 4, &expected);
git_blob_free(a);
......@@ -206,7 +206,7 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_git_pass(git_diff_blobs(
d, NULL, e, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(1, expected.files);
cl_assert_equal_i(1, expected.file_status[GIT_DELTA_DELETED]);
......@@ -222,7 +222,7 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_git_pass(git_diff_blobs(
d, NULL, e, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(1, expected.files);
cl_assert_equal_i(1, expected.file_status[GIT_DELTA_ADDED]);
......@@ -238,7 +238,7 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_git_pass(git_diff_blobs(
alien, NULL, NULL, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(1, expected.files);
cl_assert_equal_i(1, expected.files_binary);
......@@ -250,7 +250,7 @@ void test_diff_blob__can_compare_against_null_blobs(void)
cl_git_pass(git_diff_blobs(
NULL, NULL, alien, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(1, expected.files);
cl_assert_equal_i(1, expected.files_binary);
......@@ -358,7 +358,7 @@ void test_diff_blob__can_compare_identical_blobs(void)
cl_git_pass(git_diff_blobs(
d, NULL, d, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_identical_blobs_comparison(&expected);
cl_assert_equal_i(0, expected.files_binary);
......@@ -366,7 +366,7 @@ void test_diff_blob__can_compare_identical_blobs(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
NULL, NULL, NULL, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_identical_blobs_comparison(&expected);
cl_assert_equal_i(0, expected.files_binary);
......@@ -374,7 +374,7 @@ void test_diff_blob__can_compare_identical_blobs(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
alien, NULL, alien, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_identical_blobs_comparison(&expected);
cl_assert(expected.files_binary > 0);
......@@ -441,7 +441,7 @@ void test_diff_blob__can_compare_two_binary_blobs(void)
cl_git_pass(git_diff_blobs(
alien, NULL, heart, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_binary_blobs_comparison(&expected);
......@@ -449,7 +449,7 @@ void test_diff_blob__can_compare_two_binary_blobs(void)
cl_git_pass(git_diff_blobs(
heart, NULL, alien, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_binary_blobs_comparison(&expected);
......@@ -460,7 +460,7 @@ void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void)
{
cl_git_pass(git_diff_blobs(
alien, NULL, d, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_binary_blobs_comparison(&expected);
......@@ -468,7 +468,7 @@ void test_diff_blob__can_compare_a_binary_blob_and_a_text_blob(void)
cl_git_pass(git_diff_blobs(
d, NULL, alien, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_binary_blobs_comparison(&expected);
}
......@@ -510,7 +510,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
/* Test with default inter-hunk-context (not set) => default is 0 */
cl_git_pass(git_diff_blobs(
old_d, NULL, d, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(2, expected.hunks);
......@@ -519,7 +519,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
old_d, NULL, d, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(2, expected.hunks);
......@@ -528,7 +528,7 @@ void test_diff_blob__comparing_two_text_blobs_honors_interhunkcontext(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
old_d, NULL, d, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
cl_assert_equal_i(1, expected.hunks);
......@@ -542,7 +542,7 @@ void test_diff_blob__checks_options_version_too_low(void)
opts.version = 0;
cl_git_fail(git_diff_blobs(
d, NULL, alien, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
err = giterr_last();
cl_assert_equal_i(GITERR_INVALID, err->klass);
}
......@@ -554,7 +554,7 @@ void test_diff_blob__checks_options_version_too_high(void)
opts.version = 1024;
cl_git_fail(git_diff_blobs(
d, NULL, alien, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
err = giterr_last();
cl_assert_equal_i(GITERR_INVALID, err->klass);
}
......@@ -752,7 +752,7 @@ void test_diff_blob__binary_data_comparisons(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
bin, NULL, nonbin, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_binary_blobs_comparison(&expected);
/*
......@@ -773,7 +773,7 @@ void test_diff_blob__binary_data_comparisons(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_blobs(
bin, NULL, nonbin, NULL, &opts,
diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified_with_lines(&expected, 4);
/* cleanup */
......@@ -993,8 +993,8 @@ void test_diff_blob__can_compare_buffer_to_buffer(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_buffers(
a, strlen(a), NULL, b, strlen(b), NULL,
&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
a, strlen(a), NULL, b, strlen(b), NULL, &opts,
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(4, 9, 0, 4, 5, &expected);
opts.flags ^= GIT_DIFF_REVERSE;
......@@ -1002,7 +1002,7 @@ void test_diff_blob__can_compare_buffer_to_buffer(void)
memset(&expected, 0, sizeof(expected));
cl_git_pass(git_diff_buffers(
a, strlen(a), NULL, b, strlen(b), NULL,
&opts, diff_file_cb, diff_hunk_cb, diff_line_cb, &expected));
a, strlen(a), NULL, b, strlen(b), NULL, &opts,
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expected));
assert_one_modified(4, 9, 0, 5, 4, &expected);
}
......@@ -91,6 +91,18 @@ int diff_print_file_cb(
return diff_file_cb(delta, progress, payload);
}
int diff_binary_cb(
const git_diff_delta *delta,
const git_diff_binary *binary,
void *payload)
{
GIT_UNUSED(delta);
GIT_UNUSED(binary);
GIT_UNUSED(payload);
return 0;
}
int diff_hunk_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk,
......@@ -145,6 +157,7 @@ int diff_line_cb(
int diff_foreach_via_iterator(
git_diff *diff,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *data)
......
......@@ -42,6 +42,11 @@ extern int diff_print_file_cb(
float progress,
void *cb_data);
extern int diff_binary_cb(
const git_diff_delta *delta,
const git_diff_binary *binary,
void *cb_data);
extern int diff_hunk_cb(
const git_diff_delta *delta,
const git_diff_hunk *hunk,
......@@ -56,6 +61,7 @@ extern int diff_line_cb(
extern int diff_foreach_via_iterator(
git_diff *diff,
git_diff_file_cb file_cb,
git_diff_binary_cb binary_cb,
git_diff_hunk_cb hunk_cb,
git_diff_line_cb line_cb,
void *data);
......
......@@ -35,7 +35,7 @@ void test_diff_index__0(void)
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
/* to generate these values:
* - cd to tests/resources/status,
......@@ -63,7 +63,7 @@ void test_diff_index__0(void)
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, b, NULL, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
/* to generate these values:
* - cd to tests/resources/status,
......@@ -127,8 +127,8 @@ void test_diff_index__1(void)
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, NULL, &opts));
cl_assert_equal_i(
1, git_diff_foreach(diff, diff_stop_after_2_files, NULL, NULL, &exp) );
cl_assert_equal_i(1, git_diff_foreach(
diff, diff_stop_after_2_files, NULL, NULL, NULL, &exp) );
cl_assert_equal_i(2, exp.files);
......@@ -193,7 +193,7 @@ static void do_conflicted_diff(diff_expects *exp, unsigned long flags)
cl_git_pass(git_diff_tree_to_index(&diff, g_repo, a, index, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, exp));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, exp));
git_diff_free(diff);
git_tree_free(a);
......
......@@ -59,7 +59,7 @@ static void test_notify(
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(expected_diffed_files_count, exp.files);
......@@ -222,7 +222,7 @@ void test_diff_notify__notify_cb_can_be_used_as_filtering_function(void)
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, &exp));
cl_git_pass(git_diff_foreach(diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(0, exp.files);
......
......@@ -465,7 +465,7 @@ void test_diff_submodules__skips_empty_includes_used(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(0, exp.files);
git_diff_free(diff);
......@@ -478,7 +478,7 @@ void test_diff_submodules__skips_empty_includes_used(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_IGNORED]);
git_diff_free(diff);
......@@ -488,7 +488,7 @@ void test_diff_submodules__skips_empty_includes_used(void)
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &exp));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
git_diff_free(diff);
......
......@@ -49,7 +49,7 @@ void test_diff_tree__0(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(5, expect.files);
cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]);
......@@ -71,7 +71,7 @@ void test_diff_tree__0(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, b, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(2, expect.files);
cl_assert_equal_i(0, expect.file_status[GIT_DELTA_ADDED]);
......@@ -158,7 +158,7 @@ void test_diff_tree__options(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, c, d, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &actual));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &actual));
expected = &test_expects[i];
cl_assert_equal_i(actual.files, expected->files);
......@@ -194,7 +194,7 @@ void test_diff_tree__bare(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(3, expect.files);
cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]);
......@@ -235,7 +235,7 @@ void test_diff_tree__merge(void)
git_diff_free(diff2);
cl_git_pass(git_diff_foreach(
diff1, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
diff1, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(6, expect.files);
cl_assert_equal_i(2, expect.file_status[GIT_DELTA_ADDED]);
......@@ -332,7 +332,7 @@ void process_tree_to_tree_diffing(
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, NULL, NULL, &expect));
diff, diff_file_cb, NULL, NULL, NULL, &expect));
}
void test_diff_tree__symlink_blob_mode_changed_to_regular_file(void)
......@@ -441,8 +441,8 @@ void test_diff_tree__issue_1397(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, &opts));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_git_pass(git_diff_foreach(diff,
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(1, expect.files);
cl_assert_equal_i(0, expect.file_status[GIT_DELTA_DELETED]);
......@@ -472,8 +472,8 @@ void test_diff_tree__diff_configs(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_git_pass(git_diff_foreach(diff,
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(2, expect.files);
cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]);
......@@ -492,8 +492,8 @@ void test_diff_tree__diff_configs(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_git_pass(git_diff_foreach(diff,
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(2, expect.files);
cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]);
......@@ -513,8 +513,8 @@ void test_diff_tree__diff_configs(void)
cl_git_pass(git_diff_tree_to_tree(&diff, g_repo, a, b, NULL));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_git_pass(git_diff_foreach(diff,
diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &expect));
cl_assert_equal_i(2, expect.files);
cl_assert_equal_i(2, expect.file_status[GIT_DELTA_MODIFIED]);
......
......@@ -37,7 +37,7 @@ static void test_with_many(int expected_new)
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, NULL, NULL, &exp));
diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(expected_new + 2, exp.files);
......@@ -47,7 +47,7 @@ static void test_with_many(int expected_new)
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, NULL, NULL, &exp));
diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]);
cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(expected_new + 1, exp.files);
......@@ -63,7 +63,7 @@ static void test_with_many(int expected_new)
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, NULL, NULL, &exp));
diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(expected_new + 1, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(expected_new + 2, exp.files);
......@@ -73,7 +73,7 @@ static void test_with_many(int expected_new)
memset(&exp, 0, sizeof(exp));
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, NULL, NULL, &exp));
diff, diff_file_cb, NULL, NULL, NULL, &exp));
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_RENAMED]);
cl_assert_equal_i(expected_new, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(expected_new + 1, exp.files);
......
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