summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/diff.c470
-rw-r--r--src/diff.h5
2 files changed, 328 insertions, 147 deletions
diff --git a/src/diff.c b/src/diff.c
index a5b5e6198..9a12aa07c 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -12,33 +12,6 @@
#include "blob.h"
#include <ctype.h>
-static git_diff_delta *file_delta_new(
- git_diff_list *diff,
- const git_tree_diff_data *tdiff)
-{
- git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta));
-
- if (!delta) {
- git__rethrow(GIT_ENOMEM, "Could not allocate diff record");
- return NULL;
- }
-
- /* copy shared fields */
- delta->status = tdiff->status;
- delta->old_attr = tdiff->old_attr;
- delta->new_attr = tdiff->new_attr;
- delta->old_oid = tdiff->old_oid;
- delta->new_oid = tdiff->new_oid;
- delta->path = git__strdup(diff->pfx.ptr);
- if (delta->path == NULL) {
- git__free(delta);
- git__rethrow(GIT_ENOMEM, "Could not allocate diff record path");
- return NULL;
- }
-
- return delta;
-}
-
static void file_delta_free(git_diff_delta *delta)
{
if (!delta)
@@ -55,77 +28,119 @@ static void file_delta_free(git_diff_delta *delta)
git__free(delta);
}
-static int tree_add_cb(const char *root, git_tree_entry *entry, void *data)
+static int file_delta_new__from_one(
+ git_diff_list *diff,
+ git_status_t status,
+ unsigned int attr,
+ const git_oid *oid,
+ const char *path)
{
int error;
- git_diff_list *diff = data;
- ssize_t pfx_len = diff->pfx.size;
- git_tree_diff_data tdiff;
- git_diff_delta *delta;
+ git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta));
- memset(&tdiff, 0, sizeof(tdiff));
- tdiff.new_attr = git_tree_entry_attributes(entry);
- if (S_ISDIR(tdiff.new_attr))
- return GIT_SUCCESS;
+ /* This fn is just for single-sided diffs */
+ assert(status == GIT_STATUS_ADDED || status == GIT_STATUS_DELETED);
- git_oid_cpy(&tdiff.new_oid, git_tree_entry_id(entry));
- tdiff.status = GIT_STATUS_ADDED;
- tdiff.path = git_tree_entry_name(entry);
+ if (!delta)
+ return git__rethrow(GIT_ENOMEM, "Could not allocate diff record");
- if ((error = git_buf_joinpath(&diff->pfx, diff->pfx.ptr, root)) ||
- (error = git_buf_joinpath(&diff->pfx, diff->pfx.ptr, tdiff.path)))
- return error;
+ if ((delta->path = git__strdup(path)) == NULL) {
+ git__free(delta);
+ return git__rethrow(GIT_ENOMEM, "Could not allocate diff record path");
+ }
+
+ if (diff->opts.flags & GIT_DIFF_REVERSE)
+ status = (status == GIT_STATUS_ADDED) ?
+ GIT_STATUS_DELETED : GIT_STATUS_ADDED;
- delta = file_delta_new(diff, &tdiff);
- if (delta == NULL)
- error = GIT_ENOMEM;
- else if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS)
+ delta->status = status;
+
+ if (status == GIT_STATUS_ADDED) {
+ delta->new_attr = attr;
+ git_oid_cpy(&delta->new_oid, oid);
+ } else {
+ delta->old_attr = attr;
+ git_oid_cpy(&delta->old_oid, oid);
+ }
+
+ if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS)
file_delta_free(delta);
- git_buf_truncate(&diff->pfx, pfx_len);
+ return error;
+}
+
+static int file_delta_new__from_tree_diff(
+ git_diff_list *diff,
+ const git_tree_diff_data *tdiff)
+{
+ int error;
+ git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta));
+
+ if (!delta)
+ return git__rethrow(GIT_ENOMEM, "Could not allocate diff record");
+
+ if ((diff->opts.flags & GIT_DIFF_REVERSE) == 0) {
+ delta->status = tdiff->status;
+ delta->old_attr = tdiff->old_attr;
+ delta->new_attr = tdiff->new_attr;
+ delta->old_oid = tdiff->old_oid;
+ delta->new_oid = tdiff->new_oid;
+ } else {
+ /* reverse the polarity of the neutron flow */
+ switch (tdiff->status) {
+ case GIT_STATUS_ADDED: delta->status = GIT_STATUS_DELETED; break;
+ case GIT_STATUS_DELETED: delta->status = GIT_STATUS_ADDED; break;
+ default: delta->status = tdiff->status;
+ }
+ delta->old_attr = tdiff->new_attr;
+ delta->new_attr = tdiff->old_attr;
+ delta->old_oid = tdiff->new_oid;
+ delta->new_oid = tdiff->old_oid;
+ }
+
+ delta->path = git__strdup(diff->pfx.ptr);
+ if (delta->path == NULL) {
+ git__free(delta);
+ return git__rethrow(GIT_ENOMEM, "Could not allocate diff record path");
+ }
+
+ if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS)
+ file_delta_free(delta);
return error;
}
-static int tree_del_cb(const char *root, git_tree_entry *entry, void *data)
+static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data)
{
int error;
git_diff_list *diff = data;
ssize_t pfx_len = diff->pfx.size;
- git_tree_diff_data tdiff;
- git_diff_delta *delta;
- memset(&tdiff, 0, sizeof(tdiff));
- tdiff.old_attr = git_tree_entry_attributes(entry);
- if (S_ISDIR(tdiff.old_attr))
+ if (S_ISDIR(git_tree_entry_attributes(entry)))
return GIT_SUCCESS;
- git_oid_cpy(&tdiff.old_oid, git_tree_entry_id(entry));
- tdiff.status = GIT_STATUS_DELETED;
- tdiff.path = git_tree_entry_name(entry);
-
+ /* join pfx, root, and entry->filename into one */
if ((error = git_buf_joinpath(&diff->pfx, diff->pfx.ptr, root)) ||
- (error = git_buf_joinpath(&diff->pfx, diff->pfx.ptr, tdiff.path)))
+ (error = git_buf_joinpath(
+ &diff->pfx, diff->pfx.ptr, git_tree_entry_name(entry))))
return error;
- delta = file_delta_new(diff, &tdiff);
- if (delta == NULL)
- error = GIT_ENOMEM;
- else if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS)
- file_delta_free(delta);
+ error = file_delta_new__from_one(
+ diff, diff->mode, git_tree_entry_attributes(entry),
+ git_tree_entry_id(entry), diff->pfx.ptr);
git_buf_truncate(&diff->pfx, pfx_len);
return error;
}
-static int tree_diff_cb(const git_tree_diff_data *ptr, void *data)
+static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data)
{
int error;
git_diff_list *diff = data;
ssize_t pfx_len = diff->pfx.size;
- error = git_buf_joinpath(&diff->pfx, diff->pfx.ptr, ptr->path);
+ error = git_buf_joinpath(&diff->pfx, diff->pfx.ptr, tdiff->path);
if (error < GIT_SUCCESS)
return error;
@@ -138,56 +153,83 @@ static int tree_diff_cb(const git_tree_diff_data *ptr, void *data)
* and a deletion (thank you, git_tree_diff!)
* otherwise, this is a blob-to-blob diff
*/
- if (S_ISDIR(ptr->old_attr) && S_ISDIR(ptr->new_attr)) {
+ if (S_ISDIR(tdiff->old_attr) && S_ISDIR(tdiff->new_attr)) {
git_tree *old = NULL, *new = NULL;
- if (!(error = git_tree_lookup(&old, diff->repo, &ptr->old_oid)) &&
- !(error = git_tree_lookup(&new, diff->repo, &ptr->new_oid)))
- {
+ if (!(error = git_tree_lookup(&old, diff->repo, &tdiff->old_oid)) &&
+ !(error = git_tree_lookup(&new, diff->repo, &tdiff->new_oid)))
error = git_tree_diff(old, new, tree_diff_cb, diff);
- }
git_tree_free(old);
git_tree_free(new);
- } else if (S_ISDIR(ptr->old_attr) && ptr->new_attr == 0) {
- /* deleted a whole tree */
- git_tree *old = NULL;
- if (!(error = git_tree_lookup(&old, diff->repo, &ptr->old_oid))) {
- error = git_tree_walk(old, tree_del_cb, GIT_TREEWALK_POST, diff);
- git_tree_free(old);
- }
- } else if (S_ISDIR(ptr->new_attr) && ptr->old_attr == 0) {
- /* added a whole tree */
- git_tree *new = NULL;
- if (!(error = git_tree_lookup(&new, diff->repo, &ptr->new_oid))) {
- error = git_tree_walk(new, tree_add_cb, GIT_TREEWALK_POST, diff);
- git_tree_free(new);
- }
- } else {
- git_diff_delta *delta = file_delta_new(diff, ptr);
- if (delta == NULL)
- error = GIT_ENOMEM;
- else if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS)
- file_delta_free(delta);
- }
+ } else if (S_ISDIR(tdiff->old_attr) || S_ISDIR(tdiff->new_attr)) {
+ git_tree *tree = NULL;
+ int added_dir = S_ISDIR(tdiff->new_attr);
+ const git_oid *oid = added_dir ? &tdiff->new_oid : &tdiff->old_oid;
+ diff->mode = added_dir ? GIT_STATUS_ADDED : GIT_STATUS_DELETED;
+
+ if (!(error = git_tree_lookup(&tree, diff->repo, oid)))
+ error = git_tree_walk(tree, tree_walk_cb, GIT_TREEWALK_POST, diff);
+ git_tree_free(tree);
+ } else
+ error = file_delta_new__from_tree_diff(diff, tdiff);
git_buf_truncate(&diff->pfx, pfx_len);
return error;
}
+static char *git_diff_src_prefix_default = "a/";
+static char *git_diff_dst_prefix_default = "b/";
+#define PREFIX_IS_DEFAULT(A) \
+ ((A) == git_diff_src_prefix_default || (A) == git_diff_dst_prefix_default)
+
+static char *copy_prefix(const char *prefix)
+{
+ size_t len = strlen(prefix);
+ char *str = git__malloc(len + 2);
+ if (str != NULL) {
+ memcpy(str, prefix, len + 1);
+ /* append '/' at end if needed */
+ if (len > 0 && str[len - 1] != '/') {
+ str[len] = '/';
+ str[len + 1] = '\0';
+ }
+ }
+ return str;
+}
+
static git_diff_list *git_diff_list_alloc(
git_repository *repo, const git_diff_options *opts)
{
git_diff_list *diff = git__calloc(1, sizeof(git_diff_list));
- if (diff != NULL) {
- if (opts != NULL) {
- memcpy(&diff->opts, opts, sizeof(git_diff_options));
- /* do something safer with the pathspec strarray */
- }
- diff->repo = repo;
- git_buf_init(&diff->pfx, 0);
+ if (diff == NULL)
+ return NULL;
+
+ diff->repo = repo;
+ git_buf_init(&diff->pfx, 0);
+
+ if (opts == NULL)
+ return diff;
+
+ memcpy(&diff->opts, opts, sizeof(git_diff_options));
+
+ diff->opts.src_prefix = (opts->src_prefix == NULL) ?
+ git_diff_src_prefix_default : copy_prefix(opts->src_prefix);
+ diff->opts.dst_prefix = (opts->dst_prefix == NULL) ?
+ git_diff_dst_prefix_default : copy_prefix(opts->dst_prefix);
+ if (!diff->opts.src_prefix || !diff->opts.dst_prefix) {
+ git__free(diff);
+ return NULL;
+ }
+ if (diff->opts.flags & GIT_DIFF_REVERSE) {
+ char *swap = diff->opts.src_prefix;
+ diff->opts.src_prefix = diff->opts.dst_prefix;
+ diff->opts.dst_prefix = swap;
}
+
+ /* do something safe with the pathspec strarray */
+
return diff;
}
@@ -205,6 +247,14 @@ void git_diff_list_free(git_diff_list *diff)
diff->files.contents[i] = NULL;
}
git_vector_free(&diff->files);
+ if (!PREFIX_IS_DEFAULT(diff->opts.src_prefix)) {
+ git__free(diff->opts.src_prefix);
+ diff->opts.src_prefix = NULL;
+ }
+ if (!PREFIX_IS_DEFAULT(diff->opts.dst_prefix)) {
+ git__free(diff->opts.dst_prefix);
+ diff->opts.dst_prefix = NULL;
+ }
git__free(diff);
}
@@ -231,6 +281,111 @@ int git_diff_tree_to_tree(
typedef struct {
git_diff_list *diff;
+ git_index *index;
+ unsigned int index_pos;
+} index_to_tree_info;
+
+static int add_new_index_deltas(
+ index_to_tree_info *info,
+ const char *stop_path)
+{
+ int error;
+ git_index_entry *idx_entry = git_index_get(info->index, info->index_pos);
+
+ while (idx_entry != NULL &&
+ (stop_path == NULL || strcmp(idx_entry->path, stop_path) < 0))
+ {
+ error = file_delta_new__from_one(
+ info->diff, GIT_STATUS_ADDED, idx_entry->mode,
+ &idx_entry->oid, idx_entry->path);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ idx_entry = git_index_get(info->index, ++info->index_pos);
+ }
+
+ return GIT_SUCCESS;
+}
+
+static int diff_index_to_tree_cb(const char *root, git_tree_entry *tree_entry, void *data)
+{
+ int error;
+ index_to_tree_info *info = data;
+ git_index_entry *idx_entry;
+
+ /* TODO: submodule support for GIT_OBJ_COMMITs in tree */
+ if (git_tree_entry_type(tree_entry) != GIT_OBJ_BLOB)
+ return GIT_SUCCESS;
+
+ error = git_buf_joinpath(&info->diff->pfx, root, git_tree_entry_name(tree_entry));
+ if (error < GIT_SUCCESS)
+ return error;
+
+ /* create add deltas for index entries that are not in the tree */
+ error = add_new_index_deltas(info, info->diff->pfx.ptr);
+ if (error < GIT_SUCCESS)
+ return error;
+
+ /* create delete delta for tree entries that are not in the index */
+ idx_entry = git_index_get(info->index, info->index_pos);
+ if (idx_entry == NULL || strcmp(idx_entry->path, info->diff->pfx.ptr) > 0) {
+ return file_delta_new__from_one(
+ info->diff, GIT_STATUS_DELETED, git_tree_entry_attributes(tree_entry),
+ git_tree_entry_id(tree_entry), info->diff->pfx.ptr);
+ }
+
+ /* create modified delta for non-matching tree & index entries */
+ info->index_pos++;
+
+ if (git_oid_cmp(&idx_entry->oid, git_tree_entry_id(tree_entry)) ||
+ idx_entry->mode != git_tree_entry_attributes(tree_entry))
+ {
+ git_tree_diff_data tdiff;
+ tdiff.old_attr = git_tree_entry_attributes(tree_entry);
+ tdiff.new_attr = idx_entry->mode;
+ tdiff.status = GIT_STATUS_MODIFIED;
+ tdiff.path = idx_entry->path;
+ git_oid_cpy(&tdiff.old_oid, git_tree_entry_id(tree_entry));
+ git_oid_cpy(&tdiff.new_oid, &idx_entry->oid);
+
+ error = file_delta_new__from_tree_diff(info->diff, &tdiff);
+ }
+
+ return error;
+
+}
+
+int git_diff_index_to_tree(
+ git_repository *repo,
+ const git_diff_options *opts,
+ git_tree *old,
+ git_diff_list **diff_ptr)
+{
+ int error;
+ index_to_tree_info info = {0};
+
+ if ((info.diff = git_diff_list_alloc(repo, opts)) == NULL)
+ return GIT_ENOMEM;
+
+ if ((error = git_repository_index(&info.index, repo)) == GIT_SUCCESS) {
+ error = git_tree_walk(
+ old, diff_index_to_tree_cb, GIT_TREEWALK_POST, &info);
+ if (error == GIT_SUCCESS)
+ error = add_new_index_deltas(&info, NULL);
+ git_index_free(info.index);
+ }
+ git_buf_free(&info.diff->pfx);
+
+ if (error != GIT_SUCCESS)
+ git_diff_list_free(info.diff);
+ else
+ *diff_ptr = info.diff;
+
+ return error;
+}
+
+typedef struct {
+ git_diff_list *diff;
void *cb_data;
git_diff_hunk_fn hunk_cb;
git_diff_line_fn line_cb;
@@ -331,6 +486,26 @@ static int set_file_is_binary(
return GIT_SUCCESS;
}
+static void setup_xdiff_config(git_diff_options *opts, xdemitconf_t *cfg)
+{
+ memset(cfg, 0, sizeof(xdemitconf_t));
+
+ cfg->ctxlen =
+ (!opts || !opts->context_lines) ? 3 : opts->context_lines;
+ cfg->interhunkctxlen =
+ (!opts || !opts->interhunk_lines) ? 3 : opts->interhunk_lines;
+
+ if (!opts)
+ return;
+
+ if (opts->flags & GIT_DIFF_IGNORE_WHITESPACE)
+ cfg->flags |= XDF_WHITESPACE_FLAGS;
+ if (opts->flags & GIT_DIFF_IGNORE_WHITESPACE_CHANGE)
+ cfg->flags |= XDF_IGNORE_WHITESPACE_CHANGE;
+ if (opts->flags & GIT_DIFF_IGNORE_WHITESPACE_EOL)
+ cfg->flags |= XDF_IGNORE_WHITESPACE_AT_EOL;
+}
+
int git_diff_foreach(
git_diff_list *diff,
void *data,
@@ -341,17 +516,23 @@ int git_diff_foreach(
int error = GIT_SUCCESS;
diff_info di;
git_diff_delta *delta;
+ xpparam_t xdiff_params;
+ xdemitconf_t xdiff_config;
+ xdemitcb_t xdiff_callback;
di.diff = diff;
di.cb_data = data;
di.hunk_cb = hunk_cb;
di.line_cb = line_cb;
+ memset(&xdiff_params, 0, sizeof(xdiff_params));
+ setup_xdiff_config(&diff->opts, &xdiff_config);
+ memset(&xdiff_callback, 0, sizeof(xdiff_callback));
+ xdiff_callback.outf = diff_output_cb;
+ xdiff_callback.priv = &di;
+
git_vector_foreach(&diff->files, di.index, delta) {
- mmfile_t old, new;
- xpparam_t params;
- xdemitconf_t cfg;
- xdemitcb_t callback;
+ mmfile_t old_data, new_data;
/* map files */
if (hunk_cb || line_cb) {
@@ -365,12 +546,12 @@ int git_diff_foreach(
{
error = git_blob_lookup(
&delta->old_blob, diff->repo, &delta->old_oid);
- old.ptr = (char *)git_blob_rawcontent(delta->old_blob);
- old.size = git_blob_rawsize(delta->old_blob);
+ old_data.ptr = (char *)git_blob_rawcontent(delta->old_blob);
+ old_data.size = git_blob_rawsize(delta->old_blob);
} else {
delta->old_blob = NULL;
- old.ptr = "";
- old.size = 0;
+ old_data.ptr = "";
+ old_data.size = 0;
}
if (delta->status == GIT_STATUS_ADDED ||
@@ -378,21 +559,25 @@ int git_diff_foreach(
{
error = git_blob_lookup(
&delta->new_blob, diff->repo, &delta->new_oid);
- new.ptr = (char *)git_blob_rawcontent(delta->new_blob);
- new.size = git_blob_rawsize(delta->new_blob);
+ new_data.ptr = (char *)git_blob_rawcontent(delta->new_blob);
+ new_data.size = git_blob_rawsize(delta->new_blob);
} else {
delta->new_blob = NULL;
- new.ptr = "";
- new.size = 0;
+ new_data.ptr = "";
+ new_data.size = 0;
}
}
- if (diff->opts.force_text)
+ if (diff->opts.flags & GIT_DIFF_FORCE_TEXT)
delta->binary = 0;
else if ((error = set_file_is_binary(
- diff->repo, delta, &old, &new)) < GIT_SUCCESS)
+ diff->repo, delta, &old_data, &new_data)) < GIT_SUCCESS)
break;
+ /* TODO: if ignore_whitespace is set, then we *must* do text
+ * diffs to tell if a file has really been changed.
+ */
+
if (file_cb != NULL) {
error = file_cb(data, delta, (float)di.index / diff->files.length);
if (error != GIT_SUCCESS)
@@ -411,19 +596,8 @@ int git_diff_foreach(
di.delta = delta;
- memset(&params, 0, sizeof(params));
-
- memset(&cfg, 0, sizeof(cfg));
- cfg.ctxlen = diff->opts.context_lines || 3;
- cfg.interhunkctxlen = diff->opts.interhunk_lines || 3;
- if (diff->opts.ignore_whitespace)
- cfg.flags |= XDF_WHITESPACE_FLAGS;
-
- memset(&callback, 0, sizeof(callback));
- callback.outf = diff_output_cb;
- callback.priv = &di;
-
- xdl_diff(&old, &new, &params, &cfg, &callback);
+ xdl_diff(&old_data, &new_data,
+ &xdiff_params, &xdiff_config, &xdiff_callback);
git_blob_free(delta->old_blob);
delta->old_blob = NULL;
@@ -436,6 +610,7 @@ int git_diff_foreach(
}
typedef struct {
+ git_diff_list *diff;
git_diff_output_fn print_cb;
void *cb_data;
git_buf *buf;
@@ -483,7 +658,8 @@ static int print_compact(void *data, git_diff_delta *delta, float progress)
if (delta->new_path != NULL)
git_buf_printf(pi->buf, "%c\t%s%c -> %s%c\n", code,
delta->path, old_suffix, delta->new_path, new_suffix);
- else if (delta->old_attr != delta->new_attr)
+ else if (delta->old_attr != delta->new_attr &&
+ delta->old_attr != 0 && delta->new_attr != 0)
git_buf_printf(pi->buf, "%c\t%s%c (%o -> %o)\n", code,
delta->path, new_suffix, delta->old_attr, delta->new_attr);
else if (old_suffix != ' ')
@@ -506,6 +682,7 @@ int git_diff_print_compact(
git_buf buf = GIT_BUF_INIT;
print_info pi;
+ pi.diff = diff;
pi.print_cb = print_cb;
pi.cb_data = cb_data;
pi.buf = &buf;
@@ -549,15 +726,15 @@ static int print_patch_file(void *data, git_diff_delta *delta, float progress)
{
int error;
print_info *pi = data;
- const char *oldpfx = "a/";
+ const char *oldpfx = pi->diff->opts.src_prefix;
const char *oldpath = delta->path;
- const char *newpfx = "b/";
+ const char *newpfx = pi->diff->opts.dst_prefix;
const char *newpath = delta->new_path ? delta->new_path : delta->path;
GIT_UNUSED_ARG(progress);
git_buf_clear(pi->buf);
- git_buf_printf(pi->buf, "diff --git a/%s b/%s\n", delta->path, newpath);
+ git_buf_printf(pi->buf, "diff --git %s%s %s%s\n", oldpfx, delta->path, newpfx, newpath);
if ((error = print_oid_range(pi, delta)) < GIT_SUCCESS)
return error;
@@ -647,6 +824,7 @@ int git_diff_print_patch(
git_buf buf = GIT_BUF_INIT;
print_info pi;
+ pi.diff = diff;
pi.print_cb = print_cb;
pi.cb_data = cb_data;
pi.buf = &buf;
@@ -671,11 +849,17 @@ int git_diff_blobs(
diff_info di;
git_diff_delta delta;
mmfile_t old, new;
- xpparam_t params;
- xdemitconf_t cfg;
- xdemitcb_t callback;
+ xpparam_t xdiff_params;
+ xdemitconf_t xdiff_config;
+ xdemitcb_t xdiff_callback;
+
+ assert(repo);
- assert(repo && options);
+ if (options && (options->flags & GIT_DIFF_REVERSE)) {
+ git_blob *swap = old_blob;
+ old_blob = new_blob;
+ new_blob = swap;
+ }
if (old_blob) {
old.ptr = (char *)git_blob_rawcontent(old_blob);
@@ -712,21 +896,15 @@ int git_diff_blobs(
di.delta = &delta;
di.cb_data = cb_data;
di.hunk_cb = hunk_cb;
- di.line_cb = line_cb;
-
- memset(&params, 0, sizeof(params));
-
- memset(&cfg, 0, sizeof(cfg));
- cfg.ctxlen = options->context_lines || 3;
- cfg.interhunkctxlen = options->interhunk_lines || 3;
- if (options->ignore_whitespace)
- cfg.flags |= XDF_WHITESPACE_FLAGS;
+ di.line_cb = line_cb;
- memset(&callback, 0, sizeof(callback));
- callback.outf = diff_output_cb;
- callback.priv = &di;
+ memset(&xdiff_params, 0, sizeof(xdiff_params));
+ setup_xdiff_config(options, &xdiff_config);
+ memset(&xdiff_callback, 0, sizeof(xdiff_callback));
+ xdiff_callback.outf = diff_output_cb;
+ xdiff_callback.priv = &di;
- xdl_diff(&old, &new, &params, &cfg, &callback);
+ xdl_diff(&old, &new, &xdiff_params, &xdiff_config, &xdiff_callback);
return GIT_SUCCESS;
}
diff --git a/src/diff.h b/src/diff.h
index 1bb5c36f0..e7764a8eb 100644
--- a/src/diff.h
+++ b/src/diff.h
@@ -14,8 +14,11 @@
struct git_diff_list {
git_repository *repo;
git_diff_options opts;
- git_buf pfx;
git_vector files; /* vector of git_diff_file_delta */
+
+ /* the following are just used while processing the diff list */
+ git_buf pfx;
+ git_status_t mode;
};
#endif