mirror of
https://git.proxmox.com/git/libgit2
synced 2025-12-28 09:28:54 +00:00
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.
This commit is contained in:
parent
caf71ec081
commit
e47329b6d8
376
src/diff.c
376
src/diff.c
@ -10,6 +10,7 @@
|
||||
#include "diff.h"
|
||||
#include "xdiff/xdiff.h"
|
||||
#include "blob.h"
|
||||
#include "ignore.h"
|
||||
#include <ctype.h>
|
||||
|
||||
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(
|
||||
git_diff_list *diff,
|
||||
git_status_t status,
|
||||
unsigned int attr,
|
||||
git_status_t status,
|
||||
mode_t attr,
|
||||
const git_oid *oid,
|
||||
const char *path)
|
||||
const char *path)
|
||||
{
|
||||
int error;
|
||||
git_diff_delta *delta = git__calloc(1, sizeof(git_diff_delta));
|
||||
@ -57,10 +58,12 @@ static int file_delta_new__from_one(
|
||||
|
||||
if (status == GIT_STATUS_ADDED) {
|
||||
delta->new_attr = attr;
|
||||
git_oid_cpy(&delta->new_oid, oid);
|
||||
if (oid != NULL)
|
||||
git_oid_cpy(&delta->new_oid, oid);
|
||||
} else {
|
||||
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)
|
||||
@ -110,7 +113,7 @@ static int file_delta_new__from_tree_diff(
|
||||
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;
|
||||
git_diff_list *diff = data;
|
||||
@ -126,7 +129,7 @@ static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data)
|
||||
return error;
|
||||
|
||||
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_buf_truncate(&diff->pfx, pfx_len);
|
||||
@ -134,7 +137,7 @@ static int tree_walk_cb(const char *root, git_tree_entry *entry, void *data)
|
||||
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;
|
||||
git_diff_list *diff = 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)) &&
|
||||
!(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(new);
|
||||
@ -166,10 +169,11 @@ static int tree_diff_cb(const git_tree_diff_data *tdiff, void *data)
|
||||
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;
|
||||
diff->status = 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);
|
||||
error = git_tree_walk(
|
||||
tree, create_diff_for_tree_entry, GIT_TREEWALK_POST, diff);
|
||||
git_tree_free(tree);
|
||||
} else
|
||||
error = file_delta_new__from_tree_diff(diff, tdiff);
|
||||
@ -270,7 +274,8 @@ int git_diff_tree_to_tree(
|
||||
if (!diff)
|
||||
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 */
|
||||
*diff_ptr = diff;
|
||||
} else
|
||||
@ -281,12 +286,14 @@ int git_diff_tree_to_tree(
|
||||
|
||||
typedef struct {
|
||||
git_diff_list *diff;
|
||||
git_index *index;
|
||||
unsigned int index_pos;
|
||||
} index_to_tree_info;
|
||||
git_index *index;
|
||||
unsigned int index_pos;
|
||||
git_ignores *ignores;
|
||||
} diff_callback_info;
|
||||
|
||||
static int add_new_index_deltas(
|
||||
index_to_tree_info *info,
|
||||
diff_callback_info *info,
|
||||
git_status_t status,
|
||||
const char *stop_path)
|
||||
{
|
||||
int error;
|
||||
@ -296,7 +303,7 @@ static int add_new_index_deltas(
|
||||
(stop_path == NULL || strcmp(idx_entry->path, stop_path) < 0))
|
||||
{
|
||||
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);
|
||||
if (error < GIT_SUCCESS)
|
||||
return error;
|
||||
@ -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)
|
||||
{
|
||||
int error;
|
||||
index_to_tree_info *info = data;
|
||||
diff_callback_info *info = data;
|
||||
git_index_entry *idx_entry;
|
||||
|
||||
/* 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
|
||||
return error;
|
||||
|
||||
/* 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)
|
||||
return error;
|
||||
|
||||
@ -362,7 +369,7 @@ int git_diff_index_to_tree(
|
||||
git_diff_list **diff_ptr)
|
||||
{
|
||||
int error;
|
||||
index_to_tree_info info = {0};
|
||||
diff_callback_info info = {0};
|
||||
|
||||
if ((info.diff = git_diff_list_alloc(repo, opts)) == NULL)
|
||||
return GIT_ENOMEM;
|
||||
@ -371,7 +378,7 @@ int git_diff_index_to_tree(
|
||||
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);
|
||||
error = add_new_index_deltas(&info, GIT_STATUS_ADDED, NULL);
|
||||
git_index_free(info.index);
|
||||
}
|
||||
git_buf_free(&info.diff->pfx);
|
||||
@ -384,6 +391,264 @@ int git_diff_index_to_tree(
|
||||
return error;
|
||||
}
|
||||
|
||||
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;
|
||||
void *cb_data;
|
||||
@ -391,7 +656,7 @@ typedef struct {
|
||||
git_diff_line_fn line_cb;
|
||||
unsigned int index;
|
||||
git_diff_delta *delta;
|
||||
} diff_info;
|
||||
} diff_output_info;
|
||||
|
||||
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)
|
||||
{
|
||||
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 };
|
||||
|
||||
/* 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)
|
||||
!(err = read_next_int(&scan, &range.new_start)) && *scan == ',')
|
||||
err = read_next_int(&scan, &range.new_lines);
|
||||
if (!err && range.old_start >= 0 && range.new_start >= 0)
|
||||
err = di->hunk_cb(
|
||||
di->cb_data, di->delta, &range, bufs[0].ptr, bufs[0].size);
|
||||
err = info->hunk_cb(
|
||||
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;
|
||||
|
||||
/* expect " "/"-"/"+", then data, then maybe newline */
|
||||
@ -437,8 +702,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
(*bufs[0].ptr == '-') ? GIT_DIFF_LINE_DELETION :
|
||||
GIT_DIFF_LINE_CONTEXT;
|
||||
|
||||
err = di->line_cb(
|
||||
di->cb_data, di->delta, origin, bufs[1].ptr, bufs[1].size);
|
||||
err = info->line_cb(
|
||||
info->cb_data, info->delta, origin, bufs[1].ptr, bufs[1].size);
|
||||
|
||||
/* deal with adding and removing newline at EOF */
|
||||
if (err == GIT_SUCCESS && len == 3) {
|
||||
@ -447,8 +712,8 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len)
|
||||
else
|
||||
origin = GIT_DIFF_LINE_DEL_EOFNL;
|
||||
|
||||
err = di->line_cb(
|
||||
di->cb_data, di->delta, origin, bufs[2].ptr, bufs[2].size);
|
||||
err = info->line_cb(
|
||||
info->cb_data, info->delta, origin, bufs[2].ptr, bufs[2].size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,23 +781,23 @@ int git_diff_foreach(
|
||||
git_diff_line_fn line_cb)
|
||||
{
|
||||
int error = GIT_SUCCESS;
|
||||
diff_info di;
|
||||
diff_output_info info;
|
||||
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;
|
||||
info.diff = diff;
|
||||
info.cb_data = data;
|
||||
info.hunk_cb = hunk_cb;
|
||||
info.line_cb = line_cb;
|
||||
|
||||
setup_xdiff_options(&diff->opts, &xdiff_config, &xdiff_params);
|
||||
memset(&xdiff_callback, 0, sizeof(xdiff_callback));
|
||||
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;
|
||||
|
||||
/* map files */
|
||||
@ -580,7 +845,7 @@ int git_diff_foreach(
|
||||
*/
|
||||
|
||||
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)
|
||||
break;
|
||||
}
|
||||
@ -595,7 +860,7 @@ int git_diff_foreach(
|
||||
|
||||
assert(hunk_cb || line_cb);
|
||||
|
||||
di.delta = delta;
|
||||
info.delta = delta;
|
||||
|
||||
xdl_diff(&old_data, &new_data,
|
||||
&xdiff_params, &xdiff_config, &xdiff_callback);
|
||||
@ -615,7 +880,7 @@ typedef struct {
|
||||
git_diff_output_fn print_cb;
|
||||
void *cb_data;
|
||||
git_buf *buf;
|
||||
} print_info;
|
||||
} diff_print_info;
|
||||
|
||||
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)
|
||||
{
|
||||
print_info *pi = data;
|
||||
diff_print_info *pi = data;
|
||||
char code, old_suffix, new_suffix;
|
||||
|
||||
GIT_UNUSED_ARG(progress);
|
||||
@ -681,7 +946,7 @@ int git_diff_print_compact(
|
||||
{
|
||||
int error;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
print_info pi;
|
||||
diff_print_info pi;
|
||||
|
||||
pi.diff = diff;
|
||||
pi.print_cb = print_cb;
|
||||
@ -695,8 +960,7 @@ int git_diff_print_compact(
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int print_oid_range(print_info *pi, git_diff_delta *delta)
|
||||
static int print_oid_range(diff_print_info *pi, git_diff_delta *delta)
|
||||
{
|
||||
char start_oid[8], end_oid[8];
|
||||
|
||||
@ -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)
|
||||
{
|
||||
int error;
|
||||
print_info *pi = data;
|
||||
diff_print_info *pi = data;
|
||||
const char *oldpfx = pi->diff->opts.src_prefix;
|
||||
const char *oldpath = delta->path;
|
||||
const char *newpfx = pi->diff->opts.dst_prefix;
|
||||
@ -777,7 +1041,7 @@ static int print_patch_hunk(
|
||||
const char *header,
|
||||
size_t header_len)
|
||||
{
|
||||
print_info *pi = data;
|
||||
diff_print_info *pi = data;
|
||||
|
||||
GIT_UNUSED_ARG(d);
|
||||
GIT_UNUSED_ARG(r);
|
||||
@ -797,7 +1061,7 @@ static int print_patch_line(
|
||||
const char *content,
|
||||
size_t content_len)
|
||||
{
|
||||
print_info *pi = data;
|
||||
diff_print_info *pi = data;
|
||||
|
||||
GIT_UNUSED_ARG(delta);
|
||||
|
||||
@ -823,7 +1087,7 @@ int git_diff_print_patch(
|
||||
{
|
||||
int error;
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
print_info pi;
|
||||
diff_print_info pi;
|
||||
|
||||
pi.diff = diff;
|
||||
pi.print_cb = print_cb;
|
||||
@ -847,7 +1111,7 @@ int git_diff_blobs(
|
||||
git_diff_hunk_fn hunk_cb,
|
||||
git_diff_line_fn line_cb)
|
||||
{
|
||||
diff_info di;
|
||||
diff_output_info info;
|
||||
git_diff_delta delta;
|
||||
mmfile_t old, new;
|
||||
xpparam_t xdiff_params;
|
||||
@ -893,16 +1157,16 @@ int git_diff_blobs(
|
||||
delta.similarity = 0;
|
||||
delta.binary = 0;
|
||||
|
||||
di.diff = NULL;
|
||||
di.delta = δ
|
||||
di.cb_data = cb_data;
|
||||
di.hunk_cb = hunk_cb;
|
||||
di.line_cb = line_cb;
|
||||
info.diff = NULL;
|
||||
info.delta = δ
|
||||
info.cb_data = cb_data;
|
||||
info.hunk_cb = hunk_cb;
|
||||
info.line_cb = line_cb;
|
||||
|
||||
setup_xdiff_options(options, &xdiff_config, &xdiff_params);
|
||||
memset(&xdiff_callback, 0, sizeof(xdiff_callback));
|
||||
xdiff_callback.outf = diff_output_cb;
|
||||
xdiff_callback.priv = &di;
|
||||
xdiff_callback.priv = &info;
|
||||
|
||||
xdl_diff(&old, &new, &xdiff_params, &xdiff_config, &xdiff_callback);
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ struct git_diff_list {
|
||||
|
||||
/* the following are just used while processing the diff list */
|
||||
git_buf pfx;
|
||||
git_status_t mode;
|
||||
git_status_t status;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user