Commit e47329b6 by Russell Belfer

First pass of diff index to workdir implementation

This is an initial version of git_diff_workdir_to_index.  It
also includes renaming some structures and some refactoring
of the existing code so that it could be shared better with
the new function.

This is not complete since it needs a rebase to get some
new odb functions from the upstream branch.
parent caf71ec0
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "diff.h" #include "diff.h"
#include "xdiff/xdiff.h" #include "xdiff/xdiff.h"
#include "blob.h" #include "blob.h"
#include "ignore.h"
#include <ctype.h> #include <ctype.h>
static void file_delta_free(git_diff_delta *delta) static void file_delta_free(git_diff_delta *delta)
...@@ -30,10 +31,10 @@ static void file_delta_free(git_diff_delta *delta) ...@@ -30,10 +31,10 @@ static void file_delta_free(git_diff_delta *delta)
static int file_delta_new__from_one( static int file_delta_new__from_one(
git_diff_list *diff, git_diff_list *diff,
git_status_t status, git_status_t status,
unsigned int attr, mode_t attr,
const git_oid *oid, const git_oid *oid,
const char *path) const char *path)
{ {
int error; int error;
git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta)); git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta));
...@@ -57,10 +58,12 @@ static int file_delta_new__from_one( ...@@ -57,10 +58,12 @@ static int file_delta_new__from_one(
if (status == GIT_STATUS_ADDED) { if (status == GIT_STATUS_ADDED) {
delta->new_attr = attr; delta->new_attr = attr;
git_oid_cpy(&delta->new_oid, oid); if (oid != NULL)
git_oid_cpy(&delta->new_oid, oid);
} else { } else {
delta->old_attr = attr; delta->old_attr = attr;
git_oid_cpy(&delta->old_oid, oid); if (oid != NULL)
git_oid_cpy(&delta->old_oid, oid);
} }
if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS) if ((error = git_vector_insert(&diff->files, delta)) < GIT_SUCCESS)
...@@ -110,7 +113,7 @@ static int file_delta_new__from_tree_diff( ...@@ -110,7 +113,7 @@ static int file_delta_new__from_tree_diff(
return error; return error;
} }
static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data) static int create_diff_for_tree_entry(const char *root, git_tree_entry *entry, void *data)
{ {
int error; int error;
git_diff_list *diff = data; git_diff_list *diff = data;
...@@ -126,7 +129,7 @@ static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data) ...@@ -126,7 +129,7 @@ static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data)
return error; return error;
error = file_delta_new__from_one( error = file_delta_new__from_one(
diff, diff->mode, git_tree_entry_attributes(entry), diff, diff->status, git_tree_entry_attributes(entry),
git_tree_entry_id(entry), diff->pfx.ptr); git_tree_entry_id(entry), diff->pfx.ptr);
git_buf_truncate(&diff->pfx, pfx_len); git_buf_truncate(&diff->pfx, pfx_len);
...@@ -134,7 +137,7 @@ static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data) ...@@ -134,7 +137,7 @@ static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data)
return error; return error;
} }
static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data) static int tree_to_tree_diff_cb(const git_tree_diff_data *tdiff, void *data)
{ {
int error; int error;
git_diff_list *diff = data; git_diff_list *diff = data;
...@@ -158,7 +161,7 @@ static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data) ...@@ -158,7 +161,7 @@ static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data)
if (!(error = git_tree_lookup(&old, diff->repo, &tdiff->old_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_lookup(&new, diff->repo, &tdiff->new_oid)))
error = git_tree_diff(old, new, tree_diff_cb, diff); error = git_tree_diff(old, new, tree_to_tree_diff_cb, diff);
git_tree_free(old); git_tree_free(old);
git_tree_free(new); git_tree_free(new);
...@@ -166,10 +169,11 @@ static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data) ...@@ -166,10 +169,11 @@ static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data)
git_tree *tree = NULL; git_tree *tree = NULL;
int added_dir = S_ISDIR(tdiff->new_attr); int added_dir = S_ISDIR(tdiff->new_attr);
const git_oid *oid = added_dir ? &tdiff->new_oid : &tdiff->old_oid; const git_oid *oid = added_dir ? &tdiff->new_oid : &tdiff->old_oid;
diff->mode = added_dir ? GIT_STATUS_ADDED : GIT_STATUS_DELETED; diff->status = added_dir ? GIT_STATUS_ADDED : GIT_STATUS_DELETED;
if (!(error = git_tree_lookup(&tree, diff->repo, oid))) if (!(error = git_tree_lookup(&tree, diff->repo, oid)))
error = git_tree_walk(tree, tree_walk_cb, GIT_TREEWALK_POST, diff); error = git_tree_walk(
tree, create_diff_for_tree_entry, GIT_TREEWALK_POST, diff);
git_tree_free(tree); git_tree_free(tree);
} else } else
error = file_delta_new__from_tree_diff(diff, tdiff); error = file_delta_new__from_tree_diff(diff, tdiff);
...@@ -270,7 +274,8 @@ int git_diff_tree_to_tree( ...@@ -270,7 +274,8 @@ int git_diff_tree_to_tree(
if (!diff) if (!diff)
return GIT_ENOMEM; return GIT_ENOMEM;
if ((error = git_tree_diff(old, new, tree_diff_cb, diff)) == GIT_SUCCESS) { error = git_tree_diff(old, new, tree_to_tree_diff_cb, diff);
if (error == GIT_SUCCESS) {
git_buf_free(&diff->pfx); /* don't need this anymore */ git_buf_free(&diff->pfx); /* don't need this anymore */
*diff_ptr = diff; *diff_ptr = diff;
} else } else
...@@ -281,12 +286,14 @@ int git_diff_tree_to_tree( ...@@ -281,12 +286,14 @@ int git_diff_tree_to_tree(
typedef struct { typedef struct {
git_diff_list *diff; git_diff_list *diff;
git_index *index; git_index *index;
unsigned int index_pos; unsigned int index_pos;
} index_to_tree_info; git_ignores *ignores;
} diff_callback_info;
static int add_new_index_deltas( static int add_new_index_deltas(
index_to_tree_info *info, diff_callback_info *info,
git_status_t status,
const char *stop_path) const char *stop_path)
{ {
int error; int error;
...@@ -296,7 +303,7 @@ static int add_new_index_deltas( ...@@ -296,7 +303,7 @@ static int add_new_index_deltas(
(stop_path == NULL || strcmp(idx_entry->path, stop_path) < 0)) (stop_path == NULL || strcmp(idx_entry->path, stop_path) < 0))
{ {
error = file_delta_new__from_one( error = file_delta_new__from_one(
info->diff, GIT_STATUS_ADDED, idx_entry->mode, info->diff, status, idx_entry->mode,
&idx_entry->oid, idx_entry->path); &idx_entry->oid, idx_entry->path);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
...@@ -310,7 +317,7 @@ static int add_new_index_deltas( ...@@ -310,7 +317,7 @@ static int add_new_index_deltas(
static int diff_index_to_tree_cb(const char *root, git_tree_entry *tree_entry, void *data) static int diff_index_to_tree_cb(const char *root, git_tree_entry *tree_entry, void *data)
{ {
int error; int error;
index_to_tree_info *info = data; diff_callback_info *info = data;
git_index_entry *idx_entry; git_index_entry *idx_entry;
/* TODO: submodule support for GIT_OBJ_COMMITs in tree */ /* TODO: submodule support for GIT_OBJ_COMMITs in tree */
...@@ -322,7 +329,7 @@ static int diff_index_to_tree_cb(const char *root, git_tree_entry *tree_entry, v ...@@ -322,7 +329,7 @@ static int diff_index_to_tree_cb(const char *root, git_tree_entry *tree_entry, v
return error; return error;
/* create add deltas for index entries that are not in the tree */ /* create add deltas for index entries that are not in the tree */
error = add_new_index_deltas(info, info->diff->pfx.ptr); error = add_new_index_deltas(info, GIT_STATUS_ADDED, info->diff->pfx.ptr);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
return error; return error;
...@@ -362,7 +369,7 @@ int git_diff_index_to_tree( ...@@ -362,7 +369,7 @@ int git_diff_index_to_tree(
git_diff_list **diff_ptr) git_diff_list **diff_ptr)
{ {
int error; int error;
index_to_tree_info info = {0}; diff_callback_info info = {0};
if ((info.diff = git_diff_list_alloc(repo, opts)) == NULL) if ((info.diff = git_diff_list_alloc(repo, opts)) == NULL)
return GIT_ENOMEM; return GIT_ENOMEM;
...@@ -371,7 +378,7 @@ int git_diff_index_to_tree( ...@@ -371,7 +378,7 @@ int git_diff_index_to_tree(
error = git_tree_walk( error = git_tree_walk(
old, diff_index_to_tree_cb, GIT_TREEWALK_POST, &info); old, diff_index_to_tree_cb, GIT_TREEWALK_POST, &info);
if (error == GIT_SUCCESS) if (error == GIT_SUCCESS)
error = add_new_index_deltas(&info, NULL); error = add_new_index_deltas(&info, GIT_STATUS_ADDED, NULL);
git_index_free(info.index); git_index_free(info.index);
} }
git_buf_free(&info.diff->pfx); git_buf_free(&info.diff->pfx);
...@@ -385,13 +392,271 @@ int git_diff_index_to_tree( ...@@ -385,13 +392,271 @@ int git_diff_index_to_tree(
} }
typedef struct { typedef struct {
struct stat st;
mode_t mode;
char path[GIT_FLEX_ARRAY];
} workdir_entry;
#define MODE_PERMS_MASK 0777
/* TODO: need equiv of core git's "trust_executable_bit" flag? */
#define CANONICAL_PERMS(MODE) (((MODE) & 0100) ? 0755 : 0644)
#define MODE_TYPE(MODE) ((MODE) & ~MODE_PERMS_MASK)
static mode_t canonical_mode(mode_t raw_mode)
{
if (S_ISREG(raw_mode))
return S_IFREG | CANONICAL_PERMS(raw_mode);
else if (S_ISLNK(raw_mode))
return S_IFLNK;
else if (S_ISDIR(raw_mode))
return S_IFDIR;
else if (S_ISGITLINK(raw_mode))
return S_IFGITLINK;
else
return 0;
}
static int diff_workdir_insert(void *data, git_buf *dir)
{
workdir_entry *wd_entry = git__malloc(sizeof(workdir_entry) + dir->size + 2);
if (wd_entry == NULL)
return GIT_ENOMEM;
if (p_lstat(dir->ptr, &wd_entry->st) < 0) {
git__free(wd_entry);
return GIT_EOSERR;
}
git_buf_copy_cstr(wd_entry->path, dir->size + 1, dir);
wd_entry->mode = canonical_mode(wd_entry->st.st_mode);
/* suffix directories with / to mimic tree/index sort order */
if (S_ISDIR(wd_entry->st.st_mode)) {
wd_entry->path[dir->size] = '/';
wd_entry->path[dir->size+1] = '\0';
}
return git_vector_insert((git_vector *)data, wd_entry);
}
static int diff_workdir_walk(
const char *dir,
diff_callback_info *info,
int (*cb)(diff_callback_info *, workdir_entry *))
{
int error = GIT_SUCCESS;
git_vector files = GIT_VECTOR_INIT;
git_buf buf = GIT_BUF_INIT;
unsigned int i;
workdir_entry *wd_entry;
git_ignores ignores = {0}, *old_ignores = info->ignores;
if (!dir)
dir = git_repository_workdir(info->diff->repo);
if ((error = git_vector_init(&files, 0, git__strcmp_cb)) < GIT_SUCCESS ||
(error = git_buf_sets(&buf, dir)) < GIT_SUCCESS ||
(error = git_path_direach(&buf, diff_workdir_insert, &files)) < GIT_SUCCESS ||
(error = git_ignore__for_path(info->diff->repo, dir, &ignores)) < GIT_SUCCESS)
goto cleanup;
git_vector_sort(&files);
info->ignores = old_ignores;
git_vector_foreach(&files, i, wd_entry) {
if ((error = cb(info, wd_entry)) < GIT_SUCCESS)
goto cleanup;
}
cleanup:
git_vector_foreach(&files, i, wd_entry)
git__free(wd_entry);
info->ignores = old_ignores;
git_ignore__free(&ignores);
git_vector_free(&files);
git_buf_free(&buf);
return error;
}
static int found_new_workdir_entry(
diff_callback_info *info, workdir_entry *wd_entry)
{
int error;
int ignored = 0;
git_status_t status;
/* skip file types that are not trackable */
if (wd_entry->mode == 0)
return GIT_SUCCESS;
error = git_ignore__lookup(info->ignores, wd_entry->path, &ignored);
if (error < GIT_SUCCESS)
return error;
status = ignored ? GIT_STATUS_IGNORED : GIT_STATUS_UNTRACKED;
return file_delta_new__from_one(
info->diff, status, wd_entry->mode, NULL, wd_entry->path);
}
static int diff_workdir_to_index_cb(
diff_callback_info *info, workdir_entry *wd_entry)
{
int error, modified;
git_index_entry *idx_entry;
git_oid new_oid;
/* Store index entries that precede this workdir entry */
error = add_new_index_deltas(info, GIT_STATUS_DELETED, wd_entry->path);
if (error < GIT_SUCCESS)
return error;
/* Process workdir entries that are not in the index.
* These might be untracked, ignored, or special (dirs, etc).
*/
idx_entry = git_index_get(info->index, info->index_pos);
if (idx_entry == NULL || strcmp(idx_entry->path, wd_entry->path) > 0) {
git_buf dotgit = GIT_BUF_INIT;
int contains_dotgit;
if (!S_ISDIR(wd_entry->mode))
return found_new_workdir_entry(info, wd_entry);
error = git_buf_joinpath(&dotgit, wd_entry->path, DOT_GIT);
if (error < GIT_SUCCESS)
return error;
contains_dotgit = (git_path_exists(dotgit.ptr) == GIT_SUCCESS);
git_buf_free(&dotgit);
if (contains_dotgit)
/* TODO: deal with submodule or embedded repo */
return GIT_SUCCESS;
else if (git__prefixcmp(idx_entry->path, wd_entry->path) == GIT_SUCCESS)
/* there are entries in the directory in the index already,
* so recurse into it.
*/
return diff_workdir_walk(wd_entry->path, info, diff_workdir_to_index_cb);
else
/* TODO: this is not the same behavior as core git.
*
* I don't recurse into the directory once I know that no files
* in it are being tracked. But core git does and only adds an
* entry if there are non-directory entries contained under the
* dir (although, interestingly, it only shows the dir, not the
* individual entries).
*/
return found_new_workdir_entry(info, wd_entry);
}
/* create modified delta for non-matching tree & index entries */
info->index_pos++;
/* check for symlink/blob changes and split into add/del pair */
if (MODE_TYPE(wd_entry->mode) != MODE_TYPE(idx_entry->mode)) {
error = file_delta_new__from_one(
info->diff, GIT_STATUS_DELETED,
idx_entry->mode, &idx_entry->oid, idx_entry->path);
if (error < GIT_SUCCESS)
return error;
/* because of trailing slash, cannot have non-dir to dir transform */
assert(!S_ISDIR(wd_entry->mode));
return file_delta_new__from_one(
info->diff, GIT_STATUS_ADDED,
wd_entry->mode, NULL, wd_entry->path);
}
/* mode or size changed, so git blob has definitely changed */
if (wd_entry->mode != idx_entry->mode ||
wd_entry->st.st_size != idx_entry->file_size)
{
modified = 1;
memset(&new_oid, 0, sizeof(new_oid));
}
/* all other things are indicators there might be a change, so get oid */
if (!modified &&
((git_time_t)wd_entry->st.st_ctime != idx_entry->ctime.seconds ||
(git_time_t)wd_entry->st.st_mtime != idx_entry->mtime.seconds ||
(unsigned int)wd_entry->st.st_dev != idx_entry->dev ||
(unsigned int)wd_entry->st.st_ino != idx_entry->ino ||
/* TODO: need TRUST_UID_GID configs */
(unsigned int)wd_entry->st.st_uid != idx_entry->uid ||
(unsigned int)wd_entry->st.st_gid != idx_entry->gid))
{
/* calculate oid to confirm change */
if (S_ISLNK(wd_entry->st.st_mode))
error = git_odb__hashlink(&new_oid, wd_entry->path);
else {
int fd;
if ((fd = p_open(wd_entry->path, O_RDONLY)) < 0)
error = git__throw(
GIT_EOSERR, "Could not open '%s'", wd_entry->path);
else {
error = git_odb__hashfd(
&new_oid, fd, wd_entry->st.st_size, GIT_OBJ_BLOB);
p_close(fd);
}
}
if (error < GIT_SUCCESS)
return error;
modified = (git_oid_cmp(&new_oid, &idx_entry->oid) != 0);
}
/* TODO: check index flags for forced ignore changes */
if (modified) {
git_tree_diff_data tdiff;
tdiff.old_attr = idx_entry->mode;
tdiff.new_attr = wd_entry->mode;
tdiff.status = GIT_STATUS_MODIFIED;
tdiff.path = wd_entry->path;
git_oid_cpy(&tdiff.old_oid, &idx_entry->oid);
git_oid_cpy(&tdiff.new_oid, &new_oid);
error = file_delta_new__from_tree_diff(info->diff, &tdiff);
}
return error;
}
int git_diff_workdir_to_index(
git_repository *repo,
const git_diff_options *opts,
git_diff_list **diff)
{
int error;
diff_callback_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 = diff_workdir_walk(NULL, &info, diff_workdir_to_index_cb);
if (error == GIT_SUCCESS)
error = add_new_index_deltas(&info, GIT_STATUS_DELETED, NULL);
git_index_free(info.index);
}
git_buf_free(&info.diff->pfx);
if (error != GIT_SUCCESS)
git_diff_list_free(info.diff);
else
*diff = info.diff;
return error;
}
typedef struct {
git_diff_list *diff; git_diff_list *diff;
void *cb_data; void *cb_data;
git_diff_hunk_fn hunk_cb; git_diff_hunk_fn hunk_cb;
git_diff_line_fn line_cb; git_diff_line_fn line_cb;
unsigned int index; unsigned int index;
git_diff_delta *delta; git_diff_delta *delta;
} diff_info; } diff_output_info;
static int read_next_int(const char **str, int *value) static int read_next_int(const char **str, int *value)
{ {
...@@ -410,9 +675,9 @@ static int read_next_int(const char **str, int *value) ...@@ -410,9 +675,9 @@ static int read_next_int(const char **str, int *value)
static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
{ {
int err = GIT_SUCCESS; int err = GIT_SUCCESS;
diff_info *di = priv; diff_output_info *info = priv;
if (len == 1 && di->hunk_cb) { if (len == 1 && info->hunk_cb) {
git_diff_range range = { -1, 0, -1, 0 }; git_diff_range range = { -1, 0, -1, 0 };
/* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */ /* expect something of the form "@@ -%d[,%d] +%d[,%d] @@" */
...@@ -424,11 +689,11 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) ...@@ -424,11 +689,11 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
!(err = read_next_int(&scan, &range.new_start)) && *scan == ',') !(err = read_next_int(&scan, &range.new_start)) && *scan == ',')
err = read_next_int(&scan, &range.new_lines); err = read_next_int(&scan, &range.new_lines);
if (!err && range.old_start >= 0 && range.new_start >= 0) if (!err && range.old_start >= 0 && range.new_start >= 0)
err = di->hunk_cb( err = info->hunk_cb(
di->cb_data, di->delta, &range, bufs[0].ptr, bufs[0].size); info->cb_data, info->delta, &range, bufs[0].ptr, bufs[0].size);
} }
} }
else if ((len == 2 || len == 3) && di->line_cb) { else if ((len == 2 || len == 3) && info->line_cb) {
int origin; int origin;
/* expect " "/"-"/"+", then data, then maybe newline */ /* expect " "/"-"/"+", then data, then maybe newline */
...@@ -437,8 +702,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) ...@@ -437,8 +702,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
(*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION : (*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION :
GIT_DIFF_LINE_CONTEXT; GIT_DIFF_LINE_CONTEXT;
err = di->line_cb( err = info->line_cb(
di->cb_data, di->delta, origin, bufs[1].ptr, bufs[1].size); info->cb_data, info->delta, origin, bufs[1].ptr, bufs[1].size);
/* deal with adding and removing newline at EOF */ /* deal with adding and removing newline at EOF */
if (err == GIT_SUCCESS && len == 3) { if (err == GIT_SUCCESS && len == 3) {
...@@ -447,8 +712,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) ...@@ -447,8 +712,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
else else
origin = GIT_DIFF_LINE_DEL_EOFNL; origin = GIT_DIFF_LINE_DEL_EOFNL;
err = di->line_cb( err = info->line_cb(
di->cb_data, di->delta, origin, bufs[2].ptr, bufs[2].size); info->cb_data, info->delta, origin, bufs[2].ptr, bufs[2].size);
} }
} }
...@@ -516,23 +781,23 @@ int git_diff_foreach( ...@@ -516,23 +781,23 @@ int git_diff_foreach(
git_diff_line_fn line_cb) git_diff_line_fn line_cb)
{ {
int error = GIT_SUCCESS; int error = GIT_SUCCESS;
diff_info di; diff_output_info info;
git_diff_delta *delta; git_diff_delta *delta;
xpparam_t xdiff_params; xpparam_t xdiff_params;
xdemitconf_t xdiff_config; xdemitconf_t xdiff_config;
xdemitcb_t xdiff_callback; xdemitcb_t xdiff_callback;
di.diff = diff; info.diff = diff;
di.cb_data = data; info.cb_data = data;
di.hunk_cb = hunk_cb; info.hunk_cb = hunk_cb;
di.line_cb = line_cb; info.line_cb = line_cb;
setup_xdiff_options(&diff->opts, &xdiff_config, &xdiff_params); setup_xdiff_options(&diff->opts, &xdiff_config, &xdiff_params);
memset(&xdiff_callback, 0, sizeof(xdiff_callback)); memset(&xdiff_callback, 0, sizeof(xdiff_callback));
xdiff_callback.outf = diff_output_cb; xdiff_callback.outf = diff_output_cb;
xdiff_callback.priv = &di; xdiff_callback.priv = &info;
git_vector_foreach(&diff->files, di.index, delta) { git_vector_foreach(&diff->files, info.index, delta) {
mmfile_t old_data, new_data; mmfile_t old_data, new_data;
/* map files */ /* map files */
...@@ -580,7 +845,7 @@ int git_diff_foreach( ...@@ -580,7 +845,7 @@ int git_diff_foreach(
*/ */
if (file_cb != NULL) { if (file_cb != NULL) {
error = file_cb(data, delta, (float)di.index / diff->files.length); error = file_cb(data, delta, (float)info.index / diff->files.length);
if (error != GIT_SUCCESS) if (error != GIT_SUCCESS)
break; break;
} }
...@@ -595,7 +860,7 @@ int git_diff_foreach( ...@@ -595,7 +860,7 @@ int git_diff_foreach(
assert(hunk_cb || line_cb); assert(hunk_cb || line_cb);
di.delta = delta; info.delta = delta;
xdl_diff(&old_data, &new_data, xdl_diff(&old_data, &new_data,
&xdiff_params, &xdiff_config, &xdiff_callback); &xdiff_params, &xdiff_config, &xdiff_callback);
...@@ -615,7 +880,7 @@ typedef struct { ...@@ -615,7 +880,7 @@ typedef struct {
git_diff_output_fn print_cb; git_diff_output_fn print_cb;
void *cb_data; void *cb_data;
git_buf *buf; git_buf *buf;
} print_info; } diff_print_info;
static char pick_suffix(int mode) static char pick_suffix(int mode)
{ {
...@@ -632,7 +897,7 @@ static char pick_suffix(int mode) ...@@ -632,7 +897,7 @@ static char pick_suffix(int mode)
static int print_compact(void *data, git_diff_delta *delta, float progress) static int print_compact(void *data, git_diff_delta *delta, float progress)
{ {
print_info *pi = data; diff_print_info *pi = data;
char code, old_suffix, new_suffix; char code, old_suffix, new_suffix;
GIT_UNUSED_ARG(progress); GIT_UNUSED_ARG(progress);
...@@ -681,7 +946,7 @@ int git_diff_print_compact( ...@@ -681,7 +946,7 @@ int git_diff_print_compact(
{ {
int error; int error;
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
print_info pi; diff_print_info pi;
pi.diff = diff; pi.diff = diff;
pi.print_cb = print_cb; pi.print_cb = print_cb;
...@@ -695,8 +960,7 @@ int git_diff_print_compact( ...@@ -695,8 +960,7 @@ int git_diff_print_compact(
return error; return error;
} }
static int print_oid_range(diff_print_info *pi, git_diff_delta *delta)
static int print_oid_range(print_info *pi, git_diff_delta *delta)
{ {
char start_oid[8], end_oid[8]; char start_oid[8], end_oid[8];
...@@ -726,7 +990,7 @@ static int print_oid_range(print_info *pi, git_diff_delta *delta) ...@@ -726,7 +990,7 @@ static int print_oid_range(print_info *pi, git_diff_delta *delta)
static int print_patch_file(void *data, git_diff_delta *delta, float progress) static int print_patch_file(void *data, git_diff_delta *delta, float progress)
{ {
int error; int error;
print_info *pi = data; diff_print_info *pi = data;
const char *oldpfx = pi->diff->opts.src_prefix; const char *oldpfx = pi->diff->opts.src_prefix;
const char *oldpath = delta->path; const char *oldpath = delta->path;
const char *newpfx = pi->diff->opts.dst_prefix; const char *newpfx = pi->diff->opts.dst_prefix;
...@@ -777,7 +1041,7 @@ static int print_patch_hunk( ...@@ -777,7 +1041,7 @@ static int print_patch_hunk(
const char *header, const char *header,
size_t header_len) size_t header_len)
{ {
print_info *pi = data; diff_print_info *pi = data;
GIT_UNUSED_ARG(d); GIT_UNUSED_ARG(d);
GIT_UNUSED_ARG(r); GIT_UNUSED_ARG(r);
...@@ -797,7 +1061,7 @@ static int print_patch_line( ...@@ -797,7 +1061,7 @@ static int print_patch_line(
const char *content, const char *content,
size_t content_len) size_t content_len)
{ {
print_info *pi = data; diff_print_info *pi = data;
GIT_UNUSED_ARG(delta); GIT_UNUSED_ARG(delta);
...@@ -823,7 +1087,7 @@ int git_diff_print_patch( ...@@ -823,7 +1087,7 @@ int git_diff_print_patch(
{ {
int error; int error;
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
print_info pi; diff_print_info pi;
pi.diff = diff; pi.diff = diff;
pi.print_cb = print_cb; pi.print_cb = print_cb;
...@@ -847,7 +1111,7 @@ int git_diff_blobs( ...@@ -847,7 +1111,7 @@ int git_diff_blobs(
git_diff_hunk_fn hunk_cb, git_diff_hunk_fn hunk_cb,
git_diff_line_fn line_cb) git_diff_line_fn line_cb)
{ {
diff_info di; diff_output_info info;
git_diff_delta delta; git_diff_delta delta;
mmfile_t old, new; mmfile_t old, new;
xpparam_t xdiff_params; xpparam_t xdiff_params;
...@@ -893,16 +1157,16 @@ int git_diff_blobs( ...@@ -893,16 +1157,16 @@ int git_diff_blobs(
delta.similarity = 0; delta.similarity = 0;
delta.binary = 0; delta.binary = 0;
di.diff = NULL; info.diff = NULL;
di.delta = &delta; info.delta = &delta;
di.cb_data = cb_data; info.cb_data = cb_data;
di.hunk_cb = hunk_cb; info.hunk_cb = hunk_cb;
di.line_cb = line_cb; info.line_cb = line_cb;
setup_xdiff_options(options, &xdiff_config, &xdiff_params); setup_xdiff_options(options, &xdiff_config, &xdiff_params);
memset(&xdiff_callback, 0, sizeof(xdiff_callback)); memset(&xdiff_callback, 0, sizeof(xdiff_callback));
xdiff_callback.outf = diff_output_cb; xdiff_callback.outf = diff_output_cb;
xdiff_callback.priv = &di; xdiff_callback.priv = &info;
xdl_diff(&old, &new, &xdiff_params, &xdiff_config, &xdiff_callback); xdl_diff(&old, &new, &xdiff_params, &xdiff_config, &xdiff_callback);
......
...@@ -18,7 +18,7 @@ struct git_diff_list { ...@@ -18,7 +18,7 @@ struct git_diff_list {
/* the following are just used while processing the diff list */ /* the following are just used while processing the diff list */
git_buf pfx; git_buf pfx;
git_status_t mode; git_status_t status;
}; };
#endif #endif
......
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